poj 2186 Popular Cows 强连通分量 模板

86 篇文章 0 订阅

Popular Cows

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 40223 Accepted: 16381

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. 


题意:

       给你n头牛,m条关系。每条关系里有两个数x  y表示牛x崇拜牛y。现在问你,有多少牛会被其他所有的牛崇拜。

 

做法:

     先用强连通分量进行缩点,缩点后的一个分量代表这一块中的奶牛之间都是互相崇拜,再判断这个分量和其他分量之间的关系。如果存在有且只有一个强连通分量的出度为0,则这个强连通分量里的奶牛都被其他奶牛崇拜。我们来验证一下,如果存在有且只有一个强连通分量的出度为0,表示这一块里的奶牛没有崇拜别人,其他分量中的奶牛一定会有崇拜这个分量中的奶牛,为什么呢?假设,当前联通块3没有入度也没有出度,联通块1崇拜联通块2,而因为只有块3的出度为0,并且要保证块3没有入度,所以块2必须有指向块1的一条边,这样的块1和块2是一个更大的强连通分量,而这个分量的出度为0,则假设不成立,所以原命题成立。因此只要判断是不是有且只有一个强连通分量的出度为0就好,有的话再看看这个强连通分量里有多少奶牛,输出即可。

 


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
#include<vector>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=10005;
const int maxm=50005;
int n,m,head[maxn],now;
int belong[maxn],qiang,dfn[maxn],low[maxn],cnt;
int numqiang[maxn],out[maxn],fr[maxm],to[maxm],nex[maxm];
int sta[maxn],top;
vector<int> ve[maxn];

void add(int u,int v){
    fr[now]=u,to[now]=v;
    nex[now]=head[u]; head[u]=now++;
}
void tarjan(int x){
    dfn[x]=low[x]=++cnt;
    sta[++top]=x;
    for(int i=head[x];~i;i=nex[i]){
        int v=to[i];
        if(!dfn[v]){
            tarjan(v);
            low[x]=min(low[x],low[v]);
        }
        else if(!belong[v]) low[x]=min(low[x],low[v]);
    }
    if(dfn[x]==low[x]){
        qiang++;
        while(1){
            int u=sta[top--];
            belong[u]=qiang;
            if(u==x) break;
        }
    }
}
int main(){
    int x,y;
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        scanf("%d%d",&x,&y);
        add(x,y);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i]) tarjan(i);
    for(int i=1;i<=n;i++){
        int x=belong[i];
        numqiang[x]++;
    }

    for(int i=0;i<now;i++){
        int fx=belong[fr[i]],fy=belong[to[i]];
        if(fx!=fy){
            out[fx]++;
        }
    }
    int ans=0,sum=0,aim;
    for(int i=1;i<=qiang;i++){
        if(!out[i]) {
            sum++;
            aim=i;
        }
    }
    if(sum==1){
        for(int i=1;i<=n;i++){
            if(belong[i]==aim) ans++;
        }
        cout<<ans<<endl;
    }
    else cout<<"0"<<endl;

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值