恩剛剛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
1 2
2 1
2 3
Sample Output
HINT
嗯很明顯嘛先縮點。。
然後我就卡住了。。
怎麼才能判斷一個點是否被其他所有點都指到呢。。
然後就很逗比地想出了一個錯誤的解法。。
提交半天過不了,覺得是數據的問題。。
然後想了半天覺得沒有很好的樣子
然後就棄療地看了題解。。
發現只要統計出度爲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.