Popular Cows//强连通分支Kosaraju加缩点

Posted w-j-c

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Popular Cows//强连通分支Kosaraju加缩点相关的知识,希望对你有一定的参考价值。

题目:

 

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 38415   Accepted: 15658

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.

 

思路:

 

代码:

#include <iostream>
#include <vector>
using namespace std;
const int size = 1e4 + 1;
vector<int> graph[size];
vector<int> reverse[size];
int order[size];//
int pos = 0;//用于order[]的索引
bool marked[size];
bool marked2[size];
int ans = 0;//连通分支数
int DAG[size];//分离强连通分量
int out[size];//DAG的出度,一共只有强连通分支数那么多个点

void init(int N)//初始化
{
    pos = ans = 0;
    for(int i = 1; i <= N; i++)
    {
        marked[i] = false;
        marked2[i] = false;
        graph[i].clear();
        reverse[i].clear();
        DAG[i] = 0;
        out[i] = 0;
    }
}

void dfsReverseOrder(int x)
{
    marked[x] = true;
    for(int i = 0; i < reverse[x].size(); i++)
    {
        if(!marked[reverse[x][i]])
            dfsReverseOrder(reverse[x][i]);
    }
    order[pos++] = x;
}

void dfs(int x)
{
    DAG[x] = ans;
    marked2[x]  = true;
    for(int i = 0; i < graph[x].size(); i++)
    {
        if(!marked2[graph[x][i]])
        {
            dfs(graph[x][i]);
        }
        else if(DAG[graph[x][i]] != DAG[x])//和计算出度有关
            out[ans] = 1;
    }
}

void Kosaraju(int N)
{
    for(int i = 1; i <= N; i++)
    {
        if(!marked[i])
            dfsReverseOrder(i);
    }
    pos--;

    for(; pos >= 0;pos--)
    {
        if(!marked2[order[pos]])
        {
            dfs(order[pos]);
            ans++;
        }
    }
}

int main()
{
    int N, M;
    int a, b;
    while(cin >> N >> M)
    {
        init(N);
        //输入
        for(int i = 0; i < M; i++)
        {
            cin >> a >> b;
            graph[a].push_back(b);
            reverse[b].push_back(a);    
        }
        Kosaraju(N);
        int count = 0;
        int flag;
        for(int i = 0; i < ans; i++)//找出度为0的强连通分支的个数
        {
            if(out[i] == 0)
            {
                count++;
                flag = i;
            }
        }
        int num = 0;
        if(count == 1)//若只有一个出度为0的强连通分支
        {
            for(int i = 1; i <= N; i++)//计算该强连通分支内点的个数
            {
                if(DAG[i] == flag)
                    num++;
            }
            printf("%d
", num);
        }
        else 
            printf("%d
", 0);
    }
    return 0;
}

 




以上是关于Popular Cows//强连通分支Kosaraju加缩点的主要内容,如果未能解决你的问题,请参考以下文章

[POJ2186]Popular Cows(强连通分量)

Popular Cows POJ - 2186(强连通分量)

POJ 2186 Popular Cows 强连通分量模板

POJ2186 Popular Cows 强连通分量+Kosaraju+Tarjan+Garbow

POJ 2186 Popular Cows(强连通)

[poj] 2618 popular cows