【bzoj 1051】[HAOI2006]受欢迎的牛(Tarjan缩点)

原创 2016年06月18日 10:22:51

1051: [HAOI2006]受欢迎的牛

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 4091  Solved: 2194
[Submit][Status][Discuss]

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

Source

[Submit][Status][Discuss]

【题解】【Tarjan缩点,一个受欢迎的牛必定与每个点都连边,所以,缩点,把在一个强连通分量的点缩为一个,然后扫描每一条边,最后找出度为0的点】

(附:了tarjan算法的基础,这道题就可以搞了,如果存在受所有牛都欢迎的牛,那么这些牛不可能独立存在,他们要么在一个强联通块中,要么只有一头牛。那么我们可以把所有强连通块用tarjan算法处理出来,同时计算每个强连通块中点的个数。然后枚举所以的边,如果一条边的两个结点属于不同的强连通块,那么就把发出这条边的联通块的出度+1,最后寻找是否存在出度为0的强连通块,因为受所有牛的欢迎(在一个强联通块中的牛只要有一个欢迎另一头不再强连通块中的牛,那么强连通块中其他牛就欢迎)所以一定所以的强连通块都有边连向这个强联通块。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[500010],nxt[500010],p[500010],tot;
int dis[500010],dft[500010],root,cnt;
int x[500010],y[500010];
int d[500010],top;
int f[500010],size[500010],num[500010];
int n,m;
bool vis[500010];

inline int tmp(int a,int b)
{
	return a>b;
}
inline void add(int x,int y)
{
	tot++; a[tot]=y; nxt[tot]=p[x]; p[x]=tot;
}

void tarjan(int u)
{
	dis[u]=dft[u]=++cnt;
	d[++top]=u; 
	vis[u]=1;
	int v=p[u];
	while(v>=0)
	 {
	 	if(!dft[a[v]])
	 	 {
	 	 	tarjan(a[v]);
	 	 	dis[u]=min(dis[u],dis[a[v]]);
		  }
		 else
		  if(vis[a[v]]&&dis[u]>dft[a[v]]) dis[u]=dft[a[v]];
		v=nxt[v];
	 }
	int b;
	if(dis[u]==dft[u])
	 {
	 	++root;
	 	do{
	 		b=d[top--];
	 	    size[root]++;
	 		f[b]=root;
	 		vis[b]=0;
		 }while(u!=b);
	 }
	return; 
}
inline void slove()
{
	cnt=top=root=0;
	memset(dis,0,sizeof(dis));
	memset(dft,0,sizeof(dft));
	for(int i=1;i<=n;++i)
	 if(!dft[i]) tarjan(i);
	return;
}
inline void count()
{
    for(int i=1;i<=m;++i)
     if(f[x[i]]!=f[y[i]])
       num[f[x[i]]]++;
    return;
}

int main()
{
	int i,j;
	memset(p,-1,sizeof(p));
	memset(nxt,-1,sizeof(nxt));
	memset(num,0,sizeof(num));
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;++i)
	  {
	  	scanf("%d%d",&x[i],&y[i]);
	  	add(x[i],y[i]);
 	  }//不知道为什么,如果每条边只存一遍,就会WA(重复的边也要存储) 
	slove();
	count();
	int ans=0;
	for(i=1;i<=root;++i)
	  if(!num[i])
	   {
	   	if(ans)
	     {printf("0\n"); return 0;}
	    ans=i;
	   }
	printf("%d\n",size[ans]);
	return 0;
}


版权声明:本文为博主原创文章,转载请注明出处:http://blog.csdn.net/reverie_mjp

BZOJ1051: [HAOI2006]受欢迎的牛

Description 每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,...

bzoj 1051: [HAOI2006]受欢迎的牛(tarjan 缩点)

1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4024  Solved: 2156 [Submit...

笔记③:POJ Roadblocks 次短路问题代码解析(优先队列逆序排列两种方法)

笔记③:POJ Roadblocks 次短路问题代码解析(优先队列逆序排列两种方法)

算法基础篇:常见图论最短路算法(Bellman-Ford→SPFA→Dijkstra Floyd-Warshall )入门以及代码解析

巩固基础篇:常见图论算法(Bellman-Ford→SPFS→Dijkstra Floyd-Warshall )入门以及代码解析...

BZOJ1051: [HAOI2006]受欢迎的牛(强连通Tarjan 缩点)

题目链接 题意:每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C...

BZOJ 1051: [HAOI2006]受欢迎的牛 强连通分量,Tarjan缩点

Description   每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这 种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那...

bzoj1051 [HAOI2006]受欢迎的牛[图论][tarjan缩点]

Description 每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也...

【bzoj1051】 [HAOI2006]受欢迎的牛 tarjan

Description每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为...
  • LOI_DQS
  • LOI_DQS
  • 2015年10月25日 08:57
  • 778

[BZOJ 1051][HAOI2006]受欢迎的牛(强连通分量、缩点)

Description  每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这 种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛...
  • zars19
  • zars19
  • 2017年02月13日 22:27
  • 65

BZOJ1051 [HAOI2006]受欢迎的牛(强连通分量+缩点)

题目大意:给出一个有向图,求有多少个结点能被任意一个结点到达  如果图无环,当出度为0的结点只有一个时(受欢迎的牛就是这头),问题有解,否则无解(几个出度为0的结点不会到达对方) 如果图有...
  • cjk_cjk
  • cjk_cjk
  • 2015年02月02日 22:13
  • 464
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【bzoj 1051】[HAOI2006]受欢迎的牛(Tarjan缩点)
举报原因:
原因补充:

(最多只允许输入30个字)