POJ_2186_Tarjan Popular_Cows

popular_cow
#include <cstdio>
#include <cstring>
#include <climits> // INT_MAX
#include <vector>
#include <stack>
#include <algorithm>

#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)

const int N = 10000;

int n, m;
std::vector <int> graph[N], new_graph[N];

int depth[N], lowest[N], scc_count, id[N];
std::stack <int> stack;

void dfs(int p, int u) {
    if (depth[u] == -1) {
        int tmp = lowest[u] = depth[u] = p == - 1 ? 0 : depth[p] + 1;
        stack.push(u);
        foreach (iter, graph[u]) {
            int v = *iter;
            dfs(u, v);
            tmp = std::min(tmp, lowest[v]);
        }
        lowest[u] = tmp;
        if (depth[u] == lowest[u]) {
            while (true) {
                int v = stack.top();
                stack.pop();
                id[v] = scc_count;
                lowest[v] = INT_MAX; 
                if (u == v) {
                    break;
                }
            }
            scc_count ++;
        }
    }
}

bool vis[N];

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 0, a, b; i < m; ++ i) {
        scanf("%d%d", &a, &b);
        a --;
        b --;
        graph[b].push_back(a);
    }
    memset(depth, -1, sizeof(depth));
    scc_count = 0;
    for (int i = 0; i < n; ++ i) {
        dfs(-1, i);
    }
    memset(vis, 0, sizeof(vis));
    for (int i = 0; i < n; ++ i) {
        foreach (iter, graph[i]) {
            int j = *iter;
            if (id[i] != id[j]) {
                vis[id[j]] = true;
            }
        }
    }
    int ans = 0, cnt = 0, scc_ko;
    for (int i = scc_count - 1; i >= 0; -- i) {
        if (!vis[i]) {
            cnt++;
            scc_ko = i;
        }
    }
    if (cnt != 1) printf("0\n");
    else {
        for (int i = 0; i < n; i++) {
            if (id[i] == scc_ko) ++ans;
        }
        printf("%d\n", ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值