poj 2186 Popular Cows

#include<stdio.h>
#include<string.h>
#define adj 10010
#define edg 50010
struct node
{
	int v;
	int next;
};

node edge[edg];
node edge1[edg];
int low[adj],dfn[adj],Stack[adj];
int first[adj],first1[adj],fuck[adj];
bool ins[adj];
int n,m,temp,cnt,top,count;
int cnt_size[adj],belong[adj],outdegree[adj];
void creat(int u,int v)                
{
	edge1[count].next=first1[u];
	edge1[count].v=v;
	first1[u]=count++;
}

void tarjan(int u)
{
	int i,v;
	dfn[u]=low[u]=++temp;
	Stack[top++]=u;
	ins[u]=true;
	for(i=first[u];i!=-1;i=edge[i].next)
	{
		v=edge[i].v;
		if(!dfn[v])
		{
			tarjan(v);
			if(low[u]>low[v])
				low[u]=low[v];
		}
		else if(ins[v])
		{
			if(low[u]>dfn[v])
				low[u]=dfn[v];
		}
	}
	if(dfn[u]==low[u])
	{
		int j;
		do
		{
			top--;
			j=Stack[top];
			ins[j]=false;
			cnt_size[cnt]++;
			belong[j]=cnt;
		}while(u!=j);
		cnt++;
	}
}

int main()
{
	int i,j,k,v,sum,num;
	int e=0;
	scanf("%d%d",&n,&m);

    memset(first,-1,sizeof(first));
	for(k=0;k<m;k++)//建立图
	{
		scanf("%d%d",&i,&j);
		edge[e].v=j;
		edge[e].next=first[i];
		first[i]=e;
		e++;
	}

    memset(dfn,0,sizeof(dfn));
	memset(ins,false,sizeof(ins));
	temp=cnt=top=0;
	memset(cnt_size,0,sizeof(cnt_size));
	memset(low,0,sizeof(low));

	for(i=1;i<=n;i++)//求强连通分量
	{
		if(!dfn[i])
			tarjan(i);
	}

	memset(first1,-1,sizeof(first1));
	count=0;
	for(i=1;i<=n;i++)//重新构造图
	{
		for(j=first[i];j!=-1;j=edge[j].next)
		{
			v=edge[j].v;
			if(belong[i]!=belong[v])
				creat(belong[i],belong[v]);
		}
	}

	memset(outdegree,0,sizeof(outdegree));
	for(i=0;i<cnt;i++)//求每个节点的出度
	{
		for(j=first1[i];j!=-1;j=edge1[j].next)
			outdegree[i]++;
	}
	sum=num=0;
	for(i=0;i<cnt;i++)
	{
		if(outdegree[i]==0) //求节点为0的个数
		{
			sum=cnt_size[i];
			num++;
		}
	}
	if(num==1)
		printf("%d\n",sum);
	else
		printf("0\n");
	return 0;
}



题意:有N只牛,输入a,b的话,则说明b关注a,而且关注有传递性。例如c关注b,且b关注a,则c也关注a。题目问有多少只奶牛能被其他所有的奶牛关注。

把题目的模型转换:N个顶点的有向图,有M条边。求一共有多少个点,满足这样的条件:所有其它的点都可以到达这个点。这个点满足条件的充要条件是:这个点是树中唯一的出度为0的点

先求强连通分量,然后可以把强连通分量缩成一个点,因为,在强连通分量中的任意两个点可以到达,所有的点具有相同的性质,即它们分别能到达的点集都是相同的,能够到达它们的点集也是相同的。然后就重新构图,缩点后的图是没有强连通分量的,否则,可将环上所有点也缩成一个点,与极大强联通分量矛盾。所以只要找出度为0的点,并且出度为0的点只有1个 ,如果出度为0的点有多个的话,问题则无解。


你可能感兴趣的:(图论,Tarjan)