POJ - 2186 -- Popular Cows

版权声明: https://blog.csdn.net/moon_sky1999/article/details/81532221

题目来源:http://poj.org/problem?id=2186

思路:先处理出所有的强连通分量,将所有的强连通分量染色,缩点,这样原图变成了一棵有向树。如果出度为0的节点有且仅有一个,则这个节点所对应的强连通分量就是所有满足题意的节点。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <iostream>
#define ll long long
using namespace std;
const int maxn = 1e4 + 10;
int n, m, cnt, top, cur, color, head[maxn], du[maxn], dfn[maxn], low[maxn], s[maxn], g[maxn], num[maxn];
bool vis[maxn];
struct data {
    int to, next;
} e[maxn * 5];

void ins(int x, int y) {
    e[++cnt].to = y;
    e[cnt].next = head[x];
    head[x] = cnt;
}

void tarjan(int u) {
    low[u] = dfn[u] = ++cur;
    vis[u] = 1;
    s[++top] = u;
    for (int i = head[u]; i; i = e[i].next) {
        int x = e[i].to;
        if (dfn[x] == 0)tarjan(x);
        if (vis[x] && low[u] > low[x])low[u] = low[x];
    }
    if (dfn[u] == low[u]) {
        ++color;
        while (s[top + 1] != u) {
            g[s[top]] = color;
            vis[s[top]] = 0;
            num[color]++;
            top--;
        }
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    while (cin >> n >> m) {
        int x, y;
        cnt = cur = top = color = 0;
        memset(head, 0, sizeof(head));
        for (int i = 1; i <= m; ++i) {
            cin >> x >> y;
            ins(x, y);
        }
        memset(vis, 0, sizeof(vis));
        memset(s, 0, sizeof(s));
        memset(du, 0, sizeof(du));
        memset(dfn, 0, sizeof(dfn));
        memset(low, 0, sizeof(low));
        memset(num,0,sizeof(num));
        for (int i = 1; i <= n; ++i) {
            if (dfn[i] == 0) {
                tarjan(i);
            }
        }
        for (int i = 1; i <= n; ++i) {
            for (int j = head[i]; j; j = e[j].next) {
                if (g[i] != g[e[j].to]) {
                    du[g[i]]++;
                }
            }
        }
        bool ok=1;
        int ans = 0;
        for (int i = 1; i <= color; ++i) {
            if (du[i] == 0) {
                if (ans == 0)
                    ans = num[i];
                else {
                    ok = 0;
                    break;
                }
            }
        }
        if (ok) cout << ans << endl;
        else cout << 0 << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/moon_sky1999/article/details/81532221
今日推荐