poj 2186 Popular Cows(targan算法)

題目鏈接:http://poj.org/problem?id=2186


題目大意是有n只牛,如果a受到b的歡迎,b受到c的歡迎,那麼a就會受到c的歡迎,即歡迎是傳遞的。那麼問有幾頭牛是受到其他所有牛的歡迎。

首先需要把相互受歡迎即強連通的牛縮成一個點,即當作一隻牛,如果我們假定邊的指向a->b表示a受到b的歡迎,那麼滿足條件的前提是入度爲0的點一定只能有一個,如果有多個就說明每隻牛都不可能受到所有牛的歡迎,接着這個入度爲0的頂點包含的牛的數量就是要求的牛的數量。如果你邊的定義是相反的,那麼計算的就是出度。所以我的邊都是反向加入的。

代碼:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <iostream>

using namespace std;
const int maxn = 10005;
int ans = 0;

struct E {
    int to, next;
} edge[maxn*5];
int head[maxn];

int vis[maxn];
int dfn[maxn];
int low[maxn];
int belong[maxn];
bool instack[maxn];
int Stack[maxn];
int indeg[maxn];
int deep[maxn];
int index = 0, cnt = 0, top = 0;
int n, m;
inline void addEdge(int eid, int from, int to) {
    edge[eid].to = to;
    edge[eid].next = head[from];
    head[from] = eid;
}
void targan(int v) {
    dfn[v] = low[v] = ++index;
    Stack[++top] = v;
    instack[v] = true;
    for (int i = head[v]; ~i; i = edge[i].next) {
        int u = edge[i].to;
        if(!dfn[u]) {
            targan(u);
            low[v] = min(low[v], low[u]);
        }
        else if(instack[u]) {
            low[v] = min(low[v], dfn[u]);
        }
    }
    if(dfn[v] == low[v]) {
        int k;
        cnt ++;
        deep[cnt] = 0;
        do {
            k = Stack[top--];
            belong[k] = cnt;
            instack[k] = false;
            deep[cnt] ++;
        } while(k != v);
    }
}
void suo() {
    for(int i = 1; i <= n; i ++) {
        for (int j = head[i]; ~j; j = edge[j].next) {
            int to = edge[j].to;
            if(belong[i] != belong[to]) {
                indeg[belong[to]] ++;
            }
        }
    }
}
void getAns() {

    int ans = 0, flag = 0;
    for(int i = 1; i <= cnt; i ++) {
        if(flag == 1 && indeg[i] == 0) {
            printf("0\n");
            return ;
        }
        if(indeg[i] == 0) {
            ans = deep[cnt];
            flag = 1;
        }
    }
    printf("%d\n", ans);
}
void solve() {
    memset(dfn, 0, sizeof(dfn));
    for (int i = 1; i <= n; i ++) {
        if(!dfn[i]) {
            targan(i);
        }
    }
    suo();
    getAns();
}
int main() {
    int x ,y;
//    freopen("1.in", "r", stdin);
    while (scanf("%d%d", &n, &m) != EOF) {
        ans = 0;
        memset(head, -1, sizeof(head));
        for (int i = 0; i < m; i ++) {
            scanf("%d%d", &x, &y);
            addEdge(i, y, x);
        }
        solve();
    }
    return 0;
}


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