POJ 2186 Popular Cows(Tarjan + 強連通分量縮點)

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 對關係(例如 A -> B)構成一個有向圖,關係的含義爲 A -> B 爲牛 A 認爲牛 B Good。關係間具有傳遞性,若有 A -> B 、B -> C,則有 A -> C。問有多少頭牛被所有牛認爲 Good。

強連通分量縮點的經典題目。有向圖可以看成是由若干強連通分量構成的 DAG ,A 認爲 B Good 可以看成 A 可以到 B 。每一個強連通分量內的點均互相可達,則任意與他們中的點的出邊相連的點都是可達的。那麼該 DAG(強連通分量縮點後的圖) 中有且僅有一個出度爲零的點時,該點對任意點而言都是可達的。那麼題目轉化爲求強連通分量縮點後的 DAG 中是否存在唯一的點出度零。若存在,則該連通分量內的點數即爲答案,否則答案爲零。

一開始第二個 DFS 寫挫了,T 了一晚上。。。

貼個代碼以示教訓:

#include<cstdio>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
using namespace std;
const int maxn = 1e4 + 5;
int n,m;
bool vis[maxn];
vector<int> v[maxn];
stack<int> s;
int cnt[maxn],pre[maxn],dev[maxn],out[maxn],sum[maxn];
int dfs_time = 1,cou = 1;
void DFS(int x)
{
    int len = v[x].size();
    dev[x] = pre[x] = dfs_time++;
    s.push(x);
    for(int i = 0;i < len; ++i)
    {
        int u = v[x][i];
        if(!vis[u])
        {
            vis[u] = true;
            DFS(u);
            dev[x] = min(dev[x],dev[u]);
        }
        else if(!cnt[u]) dev[x] = min(dev[x],pre[u]);
    }
    if(pre[x] == dev[x])
    {
        int temp;
        while(!s.empty())
        {
            temp = s.top();
            s.pop();
            cnt[temp] = cou;
            ++sum[cou];
            if(temp == x) break;
        }
        ++cou;
    }
}
void Solve(int x)
{
    int len = v[x].size();
    for(int i = 0;i < len; ++i)
    {
        int u = v[x][i];
        if(cnt[x] != cnt[u]) out[cnt[x]]++;
        if(!vis[u])
        {
            vis[u] = true;
            Solve(u);
        }
    }
}
int main()
{
    scanf("%d %d",&n,&m);
    int x,y;
    for(int i = 0;i <= n; ++i)
    {
        cnt[i] = sum[i] = out[i] = 0;
        vis[i] = false;
    }
    for(int i = 0;i < m; ++i)
    {
        scanf("%d %d",&x,&y);
        v[x].push_back(y);
    }
    for(int i = 1;i <= n; ++i)
    {
        if(!vis[i])
        {
            vis[i] = true;
            DFS(i);
        }
    }
    memset(vis,false,sizeof(vis));
    for(int i = 1;i <= n; ++i)
    {
        if(!vis[i])
        {
            vis[i] = true;
            Solve(i);
        }
    }
    int ans = 0,num = 0;
    for(int i = 1;i < cou; ++i) if(!out[i]) ++num,ans = sum[i];
    printf("%d\n",num == 1 ? ans : 0);
    return 0;
}

發佈了123 篇原創文章 · 獲贊 14 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章