bzoj 1051
先Tarjan缩点。
然后枚举每一条边,统计每一个强连通分量出度是否为0。
如果只有一个强连通分量的出度为0那么答案就是这个强连通分量中牛的个数。
否则答案就是0。
#include<cstdio> #include<cctype> #include<algorithm> using namespace std; const int maxn=10001,maxe=50001; int read(){ char c; while(!isdigit(c=getchar())); int x=c-'0'; while(isdigit(c=getchar())) x=x*10+c-'0'; return x; } int cnt,hed[maxn],nex[maxe],lnk[maxe]; void add(int u,int v){ nex[++cnt]=hed[u]; lnk[hed[u]=cnt]=v; } int num,top,tme,sta[maxn],dfn[maxn],low[maxn],vis[maxn],tot[maxn]; void tarjan(int o){ sta[++top]=o; vis[o]=low[o]=++tme; for(int i=hed[o];i;i=nex[i]) if(!dfn[lnk[i]]){ if(!vis[lnk[i]]) tarjan(lnk[i]); low[o]=min(low[lnk[i]],low[o]); } if(low[o]==vis[o]){ ++num; while(dfn[sta[top]]=num,tot[num]++,sta[top--]!=o); } } int yes[maxn]; int main(){ int n=read(),m=read(),val=0,ans=0; while(m--){ int u=read(),v=read(); add(u,v); } for(int i=1;i<=n;i+=1) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i+=1) for(int j=hed[i];j;j=nex[j]) if(dfn[i]!=dfn[lnk[j]]){yes[dfn[i]]=1; break;} for(int i=1;i<=num;i+=1) val+=yes[i]; if(val==num-1) for(int i=1;i<=num;i+=1) if(!yes[i]) ans=tot[i]; printf("%d",ans); return 0; }