恩刚刚A掉了一道Tarjan缩点的题。。
1051: [HAOI2006]受欢迎的牛
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2152 Solved: 1131
[ Submit][ Status]
Description
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。
Input
第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B)
Output
一个数,即有多少头牛被所有的牛认为是受欢迎的。
Sample Input
3 3
1 2
2 1
2 3
1 2
2 1
2 3
Sample Output
1
HINT
100%的数据N<=10000,M<=50000
嗯很明显嘛先缩点。。
然后我就卡住了。。
怎么才能判断一个点是否被其他所有点都指到呢。。
然后就很逗比地想出了一个错误的解法。。
提交半天过不了,觉得是数据的问题。。
然后想了半天觉得没有很好的样子
然后就弃疗地看了题解。。
发现只要统计出度为0的点个数就好了
出度为0个数的点有多个,那就有0个牛
否则就是出度为0的那个点的个数。。
真是越来越逗比了啊。。
code:
var du,much,dfn,low,stack,belong,headlist:array[0..10001] of longint;
t,next:array[0..50001] of longint;
ins,vis:array[0..10001] of boolean;
ans,top,scc_cnt,v,time,x,y,num,i,j,k,n,m:longint;
procedure init;
begin
readln(n,m);
for i:=1 to n do headlist[i]:=-1;
for i:=1 to m do
begin
readln(x,y);
inc(num);
next[num]:=headlist[x];
headlist[x]:=num;
t[num]:=y;
end;
end;
function min(a,b:longint):longint;inline;
begin
if a<b then exit(a);
exit(b);
end;
procedure dfs(u:longint);inline;
var i:longint;
begin
inc(time);
dfn[u]:=time; low[u]:=time;
i:=headlist[u];
vis[u]:=true; ins[u]:=true;
inc(top);
stack[top]:=u;
while i<>-1 do
begin
if not(vis[t[i]]) then begin
dfs(t[i]);
low[u]:=min(low[u],low[t[i]]);
end
else if ins[t[i]] then low[u]:=min(low[u],dfn[t[i]]);
i:=next[i];
end;
if dfn[u]=low[u] then begin
inc(scc_cnt);
repeat
v:=stack[top];
ins[v]:=false;
dec(top);
belong[v]:=scc_cnt;
inc(much[scc_cnt]);
until u=v;
end;
end;
procedure main;
begin
init;
num:=0;
for i:=1 to n do if not(vis[i]) then dfs(i);
for x:=1 to n do
begin
i:=headlist[x];
while i<>-1 do
begin
if belong[x]<>belong[t[i]] then inc(du[belong[x]]);
i:=next[i];
end;
end;
for i:=1 to scc_cnt do
if du[i]=0 then begin
inc(num);
ans:=much[i];
end;
if num=1 then writeln(ans)
else writeln(0);
end;
begin
main;
end.