题目链接:https://www.luogu.com.cn/problem/P6154
拓扑排序+快速幂求逆元
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<queue> 4 #include<cstring> 5 using namespace std; 6 typedef long long ll; 7 const int N=500005; 8 const ll mod=998244353; 9 int n,m,tot; 10 ll ans,res; 11 queue<int> q; 12 int head[N],in[N]; 13 ll sum[N],num[N]; 14 struct node{ 15 int to,next; 16 }edge[N<<1]; 17 void add(int u,int v){ 18 edge[tot].to=v; 19 edge[tot].next=head[u]; 20 head[u]=tot++; 21 } 22 ll quick_pow(ll a,ll b){ 23 ll anss=1; 24 while(b){ 25 if(b&1) ans=ans*a%mod; 26 a=a*a%mod; 27 b>>=1; 28 } 29 return anss; 30 } 31 void toposort(){ 32 for(int i=1;i<=n;i++) if(!in[i]) q.push(i); 33 while(!q.empty()){ 34 int u=q.front(); q.pop(); 35 for(int i=head[u];i!=-1;i=edge[i].next){ 36 int v=edge[i].to; 37 in[v]--; 38 num[v]=(num[v]+num[u])%mod; 39 sum[v]=(sum[v]+sum[u]+num[u])%mod; 40 if(!in[v]) q.push(v); 41 } 42 } 43 for(int i=1;i<=n;i++){ 44 res=(res+num[i])%mod; 45 ans=(ans+sum[i])%mod; 46 } 47 } 48 int main(){ 49 scanf("%d%d",&n,&m); 50 memset(head,-1,sizeof(head)); 51 memset(num,1,sizeof(num)); 52 for(int i=1;i<=m;i++){ 53 int x,y; 54 scanf("%d%d",&x,&y); 55 add(x,y); 56 in[y]++; 57 } 58 toposort(); 59 printf("%lld ",(quick_pow(res,mod-2)*ans)%mod); 60 return 0; 61 }