题目简述:n头奶牛,给出若干个欢迎关系a b,表示a欢迎b,欢迎关系是单向的,但是是可以传递的。另外每个奶牛都是欢迎他自己的。求出被所有的奶牛欢迎的奶牛的数目
解法:先跑一遍taijan或Kosaraju算法。那么出度为0的强连通分量代表的就是受其他奶牛欢迎的,但是如果出度为0的强连通分量的个数大于1.那么则无解。因为将至少有两个分量里的奶牛互相不喜欢。所以我们的算法就是如果出度为0的强连通分量的个数是1.那么我们算出这里面点的个数就是最后的答案。
代码(tarjan):
const maxn=10005; var n,m,i,j,x,ans,sum,tot,d,u:longint; last,stack,dfn,low,rd,cd,belong:array[1..maxn] of longint; f:array[1..maxn] of boolean; next,y:array[1..maxn*5] of longint; procedure init; var i:longint; begin tot:=0; sum:=0; d:=0; ans:=0; fillchar(dfn,sizeof(dfn),0); fillchar(low,sizeof(low),0); fillchar(rd,sizeof(rd),0); fillchar(cd,sizeof(cd),0); fillchar(f,sizeof(f),false); fillchar(last,sizeof(last),0); readln(n,m); for i:=1 to m do begin readln(x,y[i]); next[i]:=last[x]; last[x]:=i; end; end; function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end; procedure tarjan(x:longint); var i:longint; begin inc(d); dfn[x]:=d; low[x]:=d; inc(tot); stack[tot]:=x; f[x]:=true; i:=last[x]; while i<>0 do begin if dfn[y[i]]=0 then begin tarjan(y[i]); low[x]:=min(low[x],low[y[i]]); end else if f[y[i]] then low[x]:=min(low[x],dfn[y[i]]); i:=next[i]; end; if low[x]=dfn[x] then begin inc(sum); repeat i:=stack[tot]; dec(tot); f[i]:=false; belong[i]:=sum; until i=x; end; end; begin while not eof do begin init; for i:=1 to n do if dfn[i]=0 then tarjan(i); for i:=1 to n do begin j:=last[i]; while j>0 do begin if belong[i]<>belong[y[j]] then begin inc(cd[belong[i]]); inc(rd[belong[y[j]]]); end; j:=next[j]; end; end; j:=0; for i:=1 to sum do if cd[i]=0 then begin inc(j); u:=j; end; for i:=1 to n do if belong[i]=u then inc(ans); if j=1 then writeln(ans) else writeln(0); end; end.
</pre><pre code_snippet_id="1631039" snippet_file_name="blog_20160331_1_5072205" name="code" class="plain">
代码(Kosaraju):
var i,j,e,f1,e1,x,y,n,m,tot,u,ans:longint; v:array[1..10000] of boolean; last,f,belong,d:array[1..10000] of longint; side:array[1..100000] of record x,y,next:longint; end; procedure add(x,y:longint); begin inc(e); side[e].x:=x; side[e].y:=y; side[e].next:=last[x]; last[x]:=e; end; procedure dfs(x:longint); var i:longint; begin v[x]:=false; i:=last[x]; while i>0 do with side[i] do begin if v[y] then dfs(y); i:=next; end; if tot=0 then begin inc(f1); f[f1]:=x; end else belong[x]:=tot; end; begin readln(n,m); for i:=1 to m do begin readln(x,y); add(x,y); end; fillchar(v,sizeof(v),true); for i:=1 to n do if v[i] then dfs(i); e1:=e; fillchar(v,sizeof(v),true); fillchar(last,sizeof(last),0); for i:=1 to e do add(side[i].y,side[i].x); for i:=n downto 1 do if v[f[i]] then begin inc(tot); dfs(f[i]); end; for i:=1 to e1 do with side[i] do if belong[x]<>belong[y] then inc(d[belong[x]]); j:=0; for i:=1 to tot do if d[i]=0 then begin inc(j); u:=i; end; for i:=1 to n do if belong[i]=u then inc(ans); if j>1 then writeln(0) else writeln(ans); end.