[Tarjan缩点]BZOJ1051 YZOI2099题解

8 篇文章 0 订阅
6 篇文章 0 订阅

恩刚刚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.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值