• Popular Cows-POJ2186Tarjan


    Time Limit: 2000MS   Memory Limit: 65536K
         

    Description

    Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M <= 50,000) ordered pairs of the form (A, B) that tell you that cow A thinks that cow B is popular. Since popularity is transitive, if A thinks B is popular and B thinks C is popular, then A will also think that C is
    popular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow.

    Input

    * Line 1: Two space-separated integers, N and M

    * Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular.

    Output

    * Line 1: A single integer that is the number of cows who are considered popular by every other cow.

    Sample Input

    3 3
    1 2
    2 1
    2 3
    

    Sample Output

    1
    

    Hint

    Cow 3 is the only cow of high popularity.

    Source

    USACO 2003 Fall

    题意:每一个奶牛都想成为牧群中最受仰慕的奶牛,在牧群中有n头奶牛,给定m对关系(A,B),表示A奶牛仰慕B奶牛。计算牧群中被其他奶牛仰慕的奶牛的数目。

    思路:将n头奶牛的m个关系将会构建一个有向图,在图中强连通分量中的任意奶牛一定是被分量中的其他奶牛仰慕。所以问题就转化为在图中将强连通分量进行缩点,在形成的新图中,如果一个强连通分量集合的出度为零,说明这个集合被其他集合仰慕,而不仰慕其他的集合,所以如果在新图中集合出度为零的数目不大于1,则为出度为零集合中奶牛的数目,如果大于1,则出度为零集合之间没有仰慕关系的,所以结果为0.

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    const int Max = 10100;
    
    typedef struct node
    {
    	int v;
    
    	int next;
    
    }Line;
    
    vector<int>G[Max];
    
    Line Li[Max*5];
    
    int Head[Max],top;
    
    int dfn[Max],low[Max],pre[Max];
    
    int num[Max],Num,Du[Max];
    
    int dep;
    
    bool vis[Max];
    
    int ans;
    
    stack<int>S;
    
    void AddEdge(int u,int v)
    {
    	Li[top].v=v ; Li[top].next=Head[u];
    
    	Head[u]=top++;
    }
    
    void Tarjan(int u)// Tarjan求强连通分量
    {
    	dfn[u]=low[u]=dep++;
    
    	S.push(u);
    	
    	for(int i=Head[u];i!=-1;i=Li[i].next)
    	{
    		if(dfn[Li[i].v]==-1)
    		{
    			Tarjan(Li[i].v);
    
    			low[u]=min(low[u],low[Li[i].v]);
    		}
    		else
    		{
    			low[u]=min(low[u],dfn[Li[i].v]);
    		}
    	}
    
    	if(low[u]==dfn[u])//强连通分量的根节点
    	{
    
    		while(!S.empty())
    		{
    			int v = S.top();
    
    			S.pop();
    
    			pre[v] = Num;//给分量集合标号
    
    			G[Num].push_back(v);//记录集合对应的点
    
    			num[Num]++;
    
    			if(v==u)
    			{
    				break;
    			}
    		}
    
    		Num++;
    	}
    
    }
    
    int main()
    {
    
    	int n,m;
    
    	while(~scanf("%d %d",&n,&m))
    	{
    		top = 0;
    
    		memset(Head,-1,sizeof(Head));
    
    		int u,v;
    
    		for(int i=0;i<m;i++)
    		{
    			scanf("%d %d",&u,&v);
    
    			AddEdge(u,v);
    		}
    
    		memset(dfn,-1,sizeof(dfn));
    	
    		memset(num,0,sizeof(num));
    
    		for(int i =0;i<=n;i++)
    		{
    			G[i].clear();
    		}
    
    		dep = 0;Num = 0;
    
    		for(int i=1;i<=n;i++)
    		{
    			if(dfn[i]==-1)
    			{
    				Tarjan(i);
    			}
    		}
    
    		memset(Du,0,sizeof(Du));
    
    		for(int i=0; i<Num ;i++) //判断强连通分量的出度
    		{
    			memset(vis,false,sizeof(vis));
    
    			for(int k=0;k<G[i].size();k++)
    			{
    				for(int j=Head[G[i][k]]; j!=-1;j=Li[j].next)
    				{
    					if(i!=pre[Li[j].v])
    					{
    						if(!vis[pre[Li[i].v]])//由于不同的强连通分量之间相连的边可能不止一条,所以要判断是不是已经统计过。
    						{
    							vis[pre[Li[i].v]]=true;
    
    							Du[i]++;
    						}
    					}
    				}
    			}
    		}
    
    		ans = 0;
    
    		int ant  = 0;
    
    		for(int i=0;i<Num;i++)//如果超过一个的出度为零的强连通分量,则这些连通分量就不能被其他的牛都仰慕。
    		{
    			if(Du[i]==0)
    			{
    				ans+=num[i];
    
    				ant++;
    
    			}
    		}
    
    
    		printf("%d
    ",ant<=1?ans:0);
    
    	}
    
    	return 0;
    }


  • 相关阅读:
    微软小冰迎来了一个新姐妹:“欣小然”
    终极之战:Linux & Windows
    逆天!百度AI音箱重磅升级:最大梦想实现
    国货之光!百度飞桨与华为麒麟重磅合作
    4天如何完爆Kafka源码核心流程!
    免费P7架构师直播课!技术人员如何提升职场技能?
    ZooKeeper核心原理及应用场景
    IT自由职业者是怎么样的感受和体验
    系统梳理主流定时器算法实现的差异以及应用
    微服务架构中分布式事务实现方案怎样何取舍
  • 原文地址:https://www.cnblogs.com/juechen/p/5255890.html
Copyright © 2020-2023  润新知