拓扑排序模板及其应用

xiaoxiao2021-02-28  19

洛谷 P3183食物链

这道题我们可以把边反向存一下。然后进行拓扑排序的时候记录一个son,根据加法原理,父亲节点能够得到的答案是由儿子们的答案和构成,初始值入度为0的节点贡献为1.最后输出的时候可以将初度为0的点的答案统计出来即可。

#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<iostream> using namespace std; struct arr{ int nd,nx; }bot[200050]; int head[100050],son[100050],rd[100050],cd[100050],q[200005]; int n,m,num,k,x; long long ans; bool vis[100050]; inline void add(int x,int y){bot[++num].nd=y;bot[num].nx=head[x];head[x]=num;rd[y]++;cd[x]++;} inline int read(){ int x=0,w=1;char ch=0; while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); if(ch=='-') w=-1,ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch-48),ch=getchar(); return x*w; } inline void tuopu(){ int l=0,r=0; for(register int i=1;i<=n;++i) if(rd[i]==0) q[++r]=i,son[i]=1; while (l!=r){ l++; register int u=q[l]; if (l==200000) l=0; for (register int i=head[u];i;i=bot[i].nx) if(vis[bot[i].nd]){ son[bot[i].nd]+=son[u]; rd[bot[i].nd]--; if (!rd[bot[i].nd]) q[++r]=bot[i].nd; if (r==200000) r=0; } } } int main(){ n=read();m=read(); for (register int i=1;i<=m;i++){ register int x=read(),y=read(); vis[x]=1;vis[y]=1; add(y,x); } tuopu(); for(register int i=1;i<=n;++i) if(!cd[i]&&vis[i])ans+=son[i]; printf("%lld\n",ans); return 0; }
转载请注明原文地址: https://www.6miu.com/read-2050226.html

最新回复(0)