[Tarjan縮點]BZOJ1051 YZOI2099題解

恩剛剛A掉了一道Tarjan縮點的題。。

1051: [HAOI2006]受歡迎的牛

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 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

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.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章