答案为 s u m c n t \frac{sum}{cnt} cntsum sum 为所有路径的总长度,cnt为所有路径的个数。
题中信息可以得到,改图形是一个DAG,可以设f(i)表示以i为起点的所有路径的总长度之和,g(i)表示以i为起点的所有路径的个数。
那么
f
(
i
)
=
∑
j
∈
s
(
f
(
j
)
+
g
(
j
)
)
f(i) = \sum_{j\in{s}}(f(j) + g(j))
f(i)=∑j∈s(f(j)+g(j)) ,
首先边长为1,对于f(j)中的所有路径,当变成由i为起点时,每个路径都要加1的长度。所以要额外增加g(i)的长度。
g
(
i
)
=
1
+
∑
j
∈
s
g
(
j
)
g(i) = 1 + \sum_{j\in{s}}g(j)
g(i)=1+∑j∈sg(j),
1是自己到自己的路径。
那么 s u m = ∑ i = 1 n f ( i ) , c n t = ∑ i = 1 n g ( i ) sum = \sum_{i=1}^{n}f(i),cnt = \sum_{i=1}^{n}g(i) sum=∑i=1nf(i),cnt=∑i=1ng(i)
转移可以建立反图,跑拓扑序。
最后对答案求逆元就行了。
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10;
const int mod = 998244353;
int ne[N],e[N],h[N],idx=1;
int d[N],g[N],f[N];
int n,m;
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void top_sort(){
queue<int> qe;
for(int i=1;i<=n;i++) if(!d[i]) qe.push(i);
while(!qe.empty()){
int t = qe.front();qe.pop();
g[t] ++;
for(int i=h[t];i;i=ne[i]){
int j = e[i];
g[j] = (g[t] + g[j]) % mod;
f[j] = (f[j] + f[t] + g[t]) % mod;
if(-- d[j] == 0) qe.push(j);
}
}
}
int qmi(int a,int b){
int res = 1;
while(b){
if(b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
signed main(){
IOS
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b; cin>>a>>b;
add(b,a);
d[a] ++;
}
top_sort();
int up = 0,down = 0;
for(int i=1;i<=n;i++) up = (up + f[i]) % mod;
for(int i=1;i<=n;i++) down = (down + g[i]) % mod;
int ans = up * qmi(down,mod-2) % mod;
cout<<ans<<endl;
return 0;
}