POJ2186(Popular Cows)

Popular Cows

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

思路

題目大概意思就是A 喜歡 B,B 喜歡 C,那麼就可以認爲A 也喜歡 C,最後求被所有牛都歡迎的牛的數量。Tarjan強連通 + 縮點,縮點完了之後直接判斷出度爲0的強連通分量。

  1. 如果出度爲0的強連通分量大於1個說明不存在,答案爲0;
  2. 如果只有一個出度爲0的點,那麼答案就是這個出度爲0的強連通分量的點數。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <cmath>
#include <cstdlib>
#pragma warning(disable:4996)
using namespace std;
const int maxn = 10005;
struct edge{
	int from;
	int to;
	int next;
}e[maxn*5];
stack<int>s;
int head[maxn];			//鏈式前向星頭
int dfn[maxn];			//時間序
int low[maxn];			//返祖時間序
int num[maxn];			//同一個強連通分量中人數
int out[maxn];			//出度
int scc[maxn];			//強連通分量數目
int dfs,cnt,tot;
inline void clear_set()
{
	cnt = tot = dfs = 0;
	memset(head,-1,sizeof(head));
	memset(dfn,0,sizeof(dfn));
	memset(num,0,sizeof(num));
	memset(scc,0,sizeof(scc));
	memset(out,0,sizeof(out));
	memset(low,0,sizeof(low));
	while(!s.empty())		s.pop();
}
inline void addedge(int x,int y)
{
	e[tot].from = x;
	e[tot].to = y;
	e[tot].next = head[x];
	head[x] = tot++;
}
inline void tarjan(int x)
{
	dfn[x] = low[x] = ++cnt;
	s.push(x);
	for(int i = head[x];~i;i = e[i].next){
		int y = e[i].to;
		if(!dfn[y]){
			tarjan(y);
			low[x] = min(low[x],low[y]);
		}
		else if(!scc[y]){
			low[x] = min(low[x],dfn[y]);
		}
	}
	if(low[x] == dfn[x]){
		dfs++;
		while(true){
			int p = s.top();
			s.pop();
			scc[p] = dfs;
			num[scc[p]]++;				//記錄該強連通分量的成員數目
			if(x == p){
				break;
			}
		}
	}
}
inline void solve(int n,int m)
{
	for(int i = 1;i <= n;i++){
		if(!dfn[i]){
			tarjan(i);
		}
	}
	for(int i = 0;i < m;i++){
		int x = e[i].from;
		int y = e[i].to;
		if(scc[x] != scc[y]){
			out[scc[x]]++;
		}
	}
	int index = 0,ans = 0;
	for(int i = 1;i <= dfs;i++){
		if(out[i] == 0){
			index = i;
			ans++;
		}
	}
	if(ans > 1){
		printf("0\n");
	}
	else{
		printf("%d\n",num[index]);
	}
}
int main()
{
	int n,m;
	while(~scanf("%d%d",&n,&m)){
		clear_set();	
		for(int i = 0;i < m;i++){
			int x,y;
			scanf("%d%d",&x,&y);
			addedge(x,y);
		}
		solve(n,m);
	}
	return 0;
}

願你走出半生,歸來仍是少年~

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