• POJ


    http://poj.org/problem?id=2186

    首先求出所有的强连通分量,分好块。然后对于每一个强连通分量,都标记下他们的出度。那么只有出度是0 的块才有可能是答案,为什么呢?因为既然你有了出度,那么就是指向了另外一个块,那么你就不能指望那个块也指向你了,因为这样会形成环,所以肯定有一个块的cow不支持你,所以你这个块就不会是popular cow

    那么就有两种情况,

    ①、出度是0的块的个数是1个,那么就是唯一的答案。

    ②、出度是0的快的个数有多个,那么答案是0, 因为至少也有一个块不支持你。

    不会存在出度为0的个数是0这样的,起码都会有一个块出度是0.

    记得清空各种数组。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    const int maxn = 1e5 + 20;
    struct Edge {
        int u, v, w, tonext;
    }e[maxn * 2];
    int first[maxn], num;
    void addEdge(int u, int v) {
        ++num;
        e[num].u = u, e[num].v = v;
        e[num].tonext = first[u];
        first[u] = num;
    }
    int DFN[maxn], low[maxn], st[maxn], top, when, vis[maxn];
    int id[maxn], toSelId, out[maxn], sum[maxn];
    void tarjan(int cur, int fa) {
        DFN[cur] = low[cur] = ++when; // 时间戳
        st[++top] = cur; //进栈
        vis[cur] = true;
        for (int i = first[cur]; i; i = e[i].tonext) {
            int v = e[i].v;
            if (!DFN[v]) { //没访问过
                tarjan(v, cur);
                low[cur] = min(low[cur], low[v]);
            } else if (vis[v]) { // 访问过,而且还在栈里
                low[cur] = min(low[cur], DFN[v]);
            }
        }
        if (low[cur] == DFN[cur]) { //这个是强连通分量的根节点。
            ++toSelId;
            do {
                id[st[top]] = toSelId;
                sum[toSelId]++;
    //            printf("%d ", st[top]);
                vis[st[top]] = false;
                top--;
            } while (cur != st[top + 1]);
    //        printf("
    ");
        }
    }
    void sloveTarjan(int n) { //防止开始枚举的节点没有出边,暴力枚举每一个节点
        memset(low, 0, sizeof low);
        memset(DFN, 0, sizeof DFN);
        memset(vis, 0, sizeof vis);
        memset(id, 0, sizeof id);
        memset(out, 0, sizeof out);
        memset(sum, 0, sizeof sum);
        top = when = toSelId = 0;
        for (int i = 1; i <= n; ++i) {
            if (!DFN[i]) {
                tarjan(i, i);
            }
        }
    }
    int n, m;
    void work() {
    //    int n, m;
    //    scanf("%d%d", &n, &m);
        num = 0;
        memset(first, 0, sizeof first);
        for (int i = 1; i <= m; ++i) {
            int u, v;
            scanf("%d%d", &u, &v);
            addEdge(u, v);
        }
        sloveTarjan(n);
        for (int i = 1; i <= n; ++i) {
            for (int j = first[i]; j; j = e[j].tonext) {
                int v = e[j].v;
                if (id[i] == id[v]) continue;
                out[id[i]]++;
            }
        }
        int has = 0;
        int ans;
        for (int i = 1; i <= toSelId; ++i) {
            if (out[i] == 0) {
                has++;
                ans = i;
            }
        }
        if (has >= 2) {
            printf("0
    ");
    //        cout << 0 << endl;
            return;
        }
        printf("%d
    ", sum[ans]);
    //    cout << sum[ans] << endl;
    }
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        while (scanf("%d%d", &n, &m) != EOF) work();
        return 0;
    }
    View Code
  • 相关阅读:
    【Win 10 应用开发】Toast通知激活应用——前台&后台
    MySQL深入理解
    mysql 索引中的USING BTREE 的意义
    关于PHP将对象数据写入日志的问题
    Golang学习笔记
    git flow 使用步骤
    git flow常用命令
    Nginx Log日志统计分析常用命令
    Nginx配置中的log_format用法梳理(设置详细的日志格式)
    回调函数的原理及PHP实例
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6624625.html
Copyright © 2020-2023  润新知