poj2186Popular Cows+tarjan缩点+建图

传送门:

题意:

给出m条关系,表示n个牛中的崇拜关系,这些关系满足传递性。问被所有牛崇拜的牛有几头;

思路:

先利用tarjan缩点,同一个点中的牛肯定就是等价的了,建立新的图,找出其中出度为0的点。如果这个点唯一,那么答案就是这个缩点中包含的所有点。

如果不唯一,那么答案不存在。因为有两个点出度为0,说明这两个点相互不羡慕,0。如果没有出度为0的点,说明缩点有问题;

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <list>
#include <iterator>

using namespace std;

const int maxn = 10009;
int n,m,dfn[maxn],low[maxn],vis[maxn],belong[maxn],tot,scc;
int num[maxn];
stack<int>s;
vector<int>mp[maxn];
vector<int>nn[maxn];
void init(){
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(vis,0,sizeof(vis));
    memset(belong,0,sizeof(belong));
    memset(num,0,sizeof(num));
    tot = 0;
    scc = 0;
    for(int i=1; i<=n; i++)
        mp[i].clear(),nn[i].clear();
    while(!s.empty())s.pop();
}
void tarjan(int x)
{
    dfn[x] = low[x] = ++tot;
    s.push(x);vis[x] = 1;
    for(int i=0; i<mp[x].size(); i++)
    {
        int v = mp[x][i];
        if(!dfn[v])
        {
            tarjan(v);
            low[x] = min(low[v],low[x]);
        }
        else if(vis[v])
        {
            low[x] = min(low[x],dfn[v]);
        }
    }
    if(low[x] == dfn[x])
    {
        scc++;
        while(1)
        {
            int o = s.top();
            s.pop();
            vis[o] = 0;
            belong[o] = scc;
            num[scc]++;
            if(o==x)break;
        }
    }
}
void solve()
{
    for(int i=1; i<=n; i++)
    {
        for(int j=0;j<mp[i].size();j++)
        {
            int v = mp[i][j];
            if(belong[v]!=belong[i])
            {
                nn[belong[i]].pb(belong[v]);
            }
        }
    }
    int cnt = 0,ans;
    for(int i=1; i<=scc; i++)
    {
        if(nn[i].size()==0)
        {
            cnt++;
            ans = i;
        }
    }
    if(cnt==1)
    {
        printf("%d\n",num[ans]);
    }
    else printf("0\n");

}
int main(){
    while(~scanf("%d%d", &n, &m))
    {
        init();
        for(int i=1; i<=m; i++)
        {
            int u,v;
            scanf("%d%d", &u, &v);
            mp[u].pb(v);
        }
        for(int i=1; i<=n; i++)
        {
            if(dfn[i]==0)tarjan(i);
        }
        solve();   
    }
    return 0;
}

 

posted @ 2018-05-21 16:13  ckxkexing  阅读(189)  评论(0编辑  收藏  举报