poj 2186 Popular Cows 强连通分量
题目大意
n头奶牛,给出若干个欢迎关系a b,表示a欢迎b,欢迎关系是单向的,但是是可以传递的。另外每个奶牛都是欢迎他自己的。求出被所有的奶牛欢迎的奶牛的数目
分析
先跑一遍taijian算法。那么出度为0的强连通分量代表的就是受其他奶牛欢迎的,但是如果出度为0的强连通分量的个数大于1那么则无解。因为将至少有两个分量里的奶牛互相不喜欢(因为他们的出度为0,不连接其他点,就不喜欢另一个同样情况的强连通分量)。所以我们的算法就是如果出度为0的强连通分量的个数是1.那么我们算出这里面点的个数就是最后的答案。
代码
const maxe=500000; maxv=20000; type rec=record x,y,w,next:longint; end; var n,m:longint; g:array[1..maxe] of rec; ls:array[1..maxv] of longint; v,a,ru,cu:array[1..maxv] of longint; low,dfn:array[1..maxv] of longint; zan:array[1..maxv] of longint; tot,ans,tot1:longint; i,j,k:longint; procedure dfs(r:longint); var i,j,k:longint; begin tot:=tot+1; zan[tot]:=r; v[r]:=1; tot1:=tot1+1; low[r]:=tot1; dfn[r]:=tot1; i:=ls[r]; while i<>0 do with g[i] do begin if dfn[y]=0 then begin dfs(y); if low[r]>low[y] then low[r]:=low[y]; end else if (low[r]>dfn[y]) and (v[y]=1) then low[r]:=dfn[y]; i:=next; end; if low[r]=dfn[r] then begin ans:=ans+1; repeat j:=zan[tot]; tot:=tot-1; a[j]:=ans; v[j]:=0; until j=r; end; end; begin readln(n,m); k:=0; ans:=0; for i:=1 to m do begin readln(j,k); with g[i] do begin x:=j; y:=k; next:=ls[x]; ls[x]:=i; end; end; for i:=1 to n do if a[i]=0 then dfs(i); for i:=1 to n do begin j:=ls[i]; while j<>0 do with g[j] do begin if a[x]<>a[y] then begin cu[a[x]]:=cu[a[x]]+1; ru[a[y]]:=ru[a[y]]+1; end; j:=next; end; end; k:=0; for i:=1 to ans do if cu[i]=0 then k:=k+1; if k<>1 then begin write(0); halt; end; k:=0; for i:=1 to ans do if cu[i]=0 then k:=i; j:=0; for i:=1 to n do if a[i]=k then j:=j+1; write(j); end.