POJ 2186-Popular Cows

Popular Cows

Time Limit:2000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u

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

给出m条崇拜链,求出所有人都崇拜的大牛数量。

还是求强连通分量的题,求强连通分量的方法之前已经表述过了。这里说一下如何判断真正的大牛……

还是基础图论知识,将强连通分量缩成点后,计算所有点的出度。如果所有点出度全为0,除非构成强连通图,否则肯定不存在大牛。而如果出度为0的点大于1的话,则必然有高冷的两个点之间不存在相互崇拜。因此计算出度后,输出出度为0的那个点中牛的数量即可。

#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <cstdio>
#include <stack>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define N 10005

vector<int> e[N];
int dfn[N], low[N],stap[N], stop,belong[N],outdeg[N],dindex, cnt;
bool instack[N];
int n, m;

void tarjan(int x){
    int y = 0;
    dfn[x]=low[x]=++dindex;
    instack[x]=true;
    stap[++stop]=x;
    for (int i=0; i<e[x].size(); i++) {
        y=e[x][i];
        if (!dfn[y]) {
            tarjan(y);
            if (low[y]<low[x]) {
                low[x]=low[y];
            }
        }
        else if (instack[y]&&dfn[y]<low[x]){
            low[x]=dfn[y];
        }
    }
    if (dfn[x]==low[x]) {
        cnt++;
        while (y!=x) {
            y=stap[stop--];
            instack[y]=false;
            belong[y]=cnt;
        }
    }
}

void solve(){
    stop=dindex=cnt=0;
    memset(dfn, 0, sizeof(dfn));
    memset(instack, 0, sizeof(instack));
    memset(outdeg, 0, sizeof(outdeg));
    for (int i=1; i<=n; i++) {
        if (!dfn[i]) {
            tarjan(i);
        }
    }
}

int main(){
    int a,b,q;
    while (~scanf("%d%d", &n,&q)) {
        for (int i=1; i<=n; ++i) {
            e[i].clear();
        }
        for (int i=1; i<=q; i++) {
            scanf("%d%d",&a,&b);
            e[a].push_back(b);
        }
        solve();
        for (int i=1; i<=n; i++) {
            int size=e[i].size();
            for (int j=0; j<size; j++) {
                if (belong[i]!=belong[e[i][j]]) {
                    outdeg[belong[i]]++;
                }
            }
        }
        int sum=0;
        for (int i=1; i<=cnt; i++) {
            if (outdeg[i]==0) {
                sum++;
            }
        }
        if (sum==1) {
            sum=0;
            for (int i=1; i<=n; i++) {
                if (outdeg[belong[i]]==0) {
                    sum++;
                }
            }
            cout<<sum<<endl;
        }
        else cout<<"0"<<endl;
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值