poj 2186 Popular Cows(强连通)

题目链接:http://poj.org/problem?id=2186

Popular Cows
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 34988 Accepted: 14257

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

[Submit]   [Go Back]   [Status]   [Discuss]

Home Page   Go Back  To top


解析:本来想着用并查集写,仔细想想,并查集好像不能写,然后百度一下这个题,看到大牛用tarjan写,哇,好难啊,思路就是,先跑一边Tarjan模板,然后把每个强连通分量看成一个点,继续找出度为0的点,如果出度为0的点就一个,并且所有的牛都在强连通分量里,然后输出哪些牛在出度为0的强连通分量里(个数),否则0

借鉴大牛博客:http://blog.csdn.net/acm_cxq/article/details/52118237

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
using namespace std;
const int N = 10009;


vector<int> mp[N];
int n, m;
int cnt, tp, dfn[N], low[N], vis[N], b[N];
int out[N];
stack<int> s;

void Tarjan(int u)
{
    low[u] = dfn[u] = ++tp;
    s.push(u);
    vis[u] = 1;
    for(int i = 0; i < mp[u].size(); i++)
    {
        int v = mp[u][i];
        if(!dfn[v])
        {
            Tarjan(v);
            if(low[v] < low[u]) low[u] = low[v];
        }
        else if(vis[v] && dfn[v] < low[u]) low[u] = dfn[v];
    }
    if(dfn[u] == low[u])
    {
        cnt++;
        while(true)
        {
            int cur = s.top(); s.pop();
            vis[cur] = 0;
            b[cur] = cnt;
            if(cur == u) break;
        }
    }
}

void solve()
{
    cnt = tp = 0;
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    memset(vis, 0, sizeof(vis));
    memset(b, 0, sizeof(b));
    for(int i = 1; i <= n; i++)
    {
        if(!dfn[i]) Tarjan(i);
    }
}



int main()
{
    int u, v;
    while(~scanf("%d%d", &n, &m))
    {
        for(int i = 0; i <= n; i++) mp[i].clear();
        while(m--)
        {
            scanf("%d%d", &u, &v);
            mp[u].push_back(v);
        }
        solve();
        memset(out, 0, sizeof(out));
        for(int i = 1; i <= n; i++)
        {
            for(int j = 0; j < mp[i].size(); j++)
            {
                int v = mp[i][j];
                if(b[i] != b[v]) out[b[i]]++;
            }
        }
        int v, tol = 0;
        for(int i = 1; i <= cnt; i++)
        {
            if(!out[i])
            {
                tol++;
                v = i;
            }
        }
        for(int i = 1; i <= n; i++) if(!b[i]) tol = 0;
        if(tol == 1)
        {
            int ans = 0;
            for(int i = 1; i <= n; i++)
            {
                if(b[i] == v) ans++;
            }
            printf("%d\n", ans);
        }
        else puts("0");
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值