POJ 2186 —— 分解強連通分量

Popular Cows
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 20933   Accepted: 8530

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

題意是有n頭牛,m個關係,代表牛A認爲牛B是明星,關係具有傳遞性:A->B 且B->C 則A->C。輸出被所有牛都認爲是明星的牛數。下面爲了方便把這種牛稱爲超級牛。

思路:在一個圖的SCC中如果有一頭超級牛,則這個SCC中所有牛都是超級牛。分解SCC後,至多有一個SCC滿足題意,就是拓撲序最後的SCC,然後我們去檢查這個SCC是否是所有頂點都可以到達的,rdfs一次即可,最後輸出該SCC的節點數。

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
using namespace std;
///#define Online_Judge
#define outstars cout << "***********************" << endl;
#define clr(a,b) memset(a,b,sizeof(a))
#define lson l , mid  , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
#define mk make_pair
#define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++)
#define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++)
#define REP(i , x , n) for(int i = (x) ; i > (n) ; i--)
#define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--)
const int MAX_V = 10000 + 50;
const int MAXS = 50000 + 50;
const int sigma_size = 26;
const long long LLMAX = 0x7fffffffffffffffLL;
const long long LLMIN = 0x8000000000000000LL;
const int INF = 0x7fffffff;
const int IMIN = 0x80000000;
const int inf = 1 << 30;
#define eps 1e-10
const long long MOD = 1000000000 + 7;
const int mod = 10007;
typedef long long LL;
const double PI = acos(-1.0);
typedef double D;
typedef pair<int , int> pii;
typedef vector<int> vec;
typedef vector<vec> mat;


#define Bug(s) cout << "s = " << s << endl;
///#pragma comment(linker, "/STACK:102400000,102400000")
int V;///頂點數
vector<int> G[MAX_V];///圖的鄰接表表示
vector<int> rG[MAX_V];///把邊反向之後的圖
vector<int> vs;///後序遍歷順序的頂點列表
bool used[MAX_V];///訪問標記
int cmp[MAX_V];///所屬強聯通分量的拓撲序
void add_edge(int from , int to)
{
    G[from].push_back(to);
    rG[to].push_back(from);
}
void dfs(int v)
{
    used[v] = true;
    for(int i =  0; i < G[v].size() ; i++)
    {
        if(!used[G[v][i]])dfs(G[v][i]);
    }
    vs.push_back(v);
}
void rdfs(int v , int k)
{
    used[v] = true;
    cmp[v] = k;
    for(int i = 0 ; i < rG[v].size() ; i++)
    {
        if(!used[rG[v][i]])rdfs(rG[v][i] , k);
    }
}
int scc()
{
    memset(used , 0 , sizeof(used));
    vs.clear();
    for(int v = 0 ; v < V ; v++)
    {
        if(!used[v])dfs(v);
    }
    memset(used , 0 , sizeof(used));
    int k = 0;
    for(int i = vs.size() - 1 ; i >= 0 ; i--)
    {
        if(!used[vs[i]])rdfs(vs[i] , k++);
    }
    return k;
}
int n , m;
int a[MAXS] , b[MAXS];
void solve()
{
    V = n;
    for(int i = 0 ; i < m ; i ++)add_edge(a[i] - 1 , b[i] - 1);
    int numofscc = scc();
    int u = 0 , num = 0;
    for(int v = 0 ; v < V ; v++)
    {
        if(cmp[v] == numofscc - 1)
        {
            u = v;
            num++;
        }
    }
    memset(used ,0 , sizeof(used));
    rdfs(u , 0);
    for(int v = 0 ; v < V ; v++)
    {
        if(!used[v])
        {
            num = 0;
            break;
        }
    }
    printf("%d\n" , num);
}
int main()
{
    while(~scanf("%d%d" , &n , &m))
    {
        for(int i = 0 ; i < m ; i++)
        {
            scanf("%d%d" , &a[i] , &b[i]);
        }
        solve();
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章