解法:拓扑排序 + DP
以
为终点的路径总数,由于题目说可以自己到自己,所以直接全部初始化为
计算公式:
以
为终点的所有路径的长度之和
计算公式:
其中 表示以
为终点长度为
的路径数量
显然在拓扑排序
的过程中:
对于
: 每条以
为终点的路径都可以加上
这一条边从而形成以
为终点的路径,
对
的贡献为
,即
对于
: 显然
,所以
对
的贡献为
,即
因此只需要一边拓扑排序一边转移,最终答案=所有路径的长度/路径总数,即 /
注意:不能忽略重边的影响,也需要考虑!
(请自动忽略代码中的一些不良习惯和一大堆没用的火车头)
/*
* @Author: Phon
* @Date: 2024-10-10 22:42:14
* @Last Modified by: Phon
* @Last Modified time: 2025-11-14 23:19:02
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long i64;
typedef unsigned long long u64;
typedef __int128_t i128;
typedef double db;
#define int long long
typedef pair<int, int> PII;
constexpr int MAXN = 3e3 + 100;
constexpr i64 INF = 1e18;
// constexpr int mod = 1e9 + 7;
constexpr i64 mod = 998244353;
// int mod;
// i64 Pow (i64 a, i64 k, i64 mod) {i64 ans=1;for(;k;k>>=1,a=1ll*a*a%mod)if(k&1)ans=1ll*ans*a%mod;return ans;}
i64 Pow (i64 a, i64 k, i64 mod) {i128 ans=1;for(;k;k>>=1,a=(i128)a*a%mod)if(k&1)ans=(i128)ans*a%mod;return (i64)ans;}
i64 inv (i64 x, i64 mod) {return Pow(x,mod - 2,mod);}
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1}; // 下, 右, 上, 左
// int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1}; // 上, 下, 左, 右
inline void pre_work(){
}
using a4 = array<int, 4>;
using a3 = array<int, 3>;
using a2 = array<int, 2>;
int chmax(int &x, int y){
if(x < y){
x = y;
return 1;
}else return 0;
}
int chmin(int &x, int y){
if(x > y){
x = y;
return 1;
}else return 0;
}
template <typename _T>
inline void read(_T &f) {
f = 0; _T fu = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') { fu = -1; } c = getchar(); }
while (c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = getchar(); }
f *= fu;
}
template <typename T>
void print(T x) {
if (x < 0) putchar('-'), x = -x;
if (x < 10) putchar(x + 48);
else print(x / 10), putchar(x % 10 + 48);
}
inline void solve() {
int n, m;
cin >> n >> m;
vector<vector<int>> edge(n + 1);
vector<int> in(n + 1);
for(int i = 0; i < m; i ++){
int u, v;
cin >> u >> v;
edge[u].push_back(v), in[v] ++;
}
vector<int> f(n + 1, 1), g(n + 1);
queue<int> q;
for(int i = 1; i <= n; i ++){
if(!in[i]) q.push(i);
}
while(!q.empty()){
auto u = q.front();
q.pop();
for(auto v : edge[u]){
f[v] = (f[v] + f[u]) % mod;
g[v] = (g[v] + g[u] + f[u]) % mod;
if(--in[v] == 0){
q.push(v);
}
}
}
int zi = 0, mu = 0;
for(int i = 1; i <= n; i ++){
zi = (zi + g[i]) % mod;
mu = (mu + f[i]) % mod;
}
cout << zi * inv(mu, mod) % mod << '\n';
}
/*
*/
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int T = 1;
// cin >> T;
pre_work();
while(T--)
solve();
return 0;
}

京公网安备 11010502036488号