zoukankan      html  css  js  c++  java
  • bzoj 1051 [HAOI2006]受欢迎的牛(tarjan缩点)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1051

    题解:缩点之后判断出度为0的有几个,只有一个那么输出那个强连通块的点数,否者就输出0

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <map>
    using namespace std;
    const int N = 1e6 + 10;
    const int M = 5e6 + 10;
    map<int,int>mmp[N];
    struct TnT {
        int v, next;
    }edge[M];
    int head[N], e;
    int Low[N], DFN[N], Stack[N], Belong[N], num[N];
    int Index, top, scc;
    int Out[N];
    bool Instack[N];
    void init() {
        memset(head, -1, sizeof(head));
        e = 0;
    }
    void add(int u, int v) {
        edge[e].v = v;
        edge[e].next = head[u];
        head[u] = e++;
    }
    void Tarjan(int u) {
        int v;
        Low[u] = DFN[u] = ++Index;
        Stack[top++] = u;
        Instack[u] = true;
        for(int i = head[u]; i != -1; i = edge[i].next) {
            v = edge[i].v;
            if(!DFN[v]) {
                Tarjan(v);
                Low[u] = min(Low[u] , Low[v]);
            } else if(Instack[v]) Low[u] = min(Low[u] , DFN[v]);
        }
        if(DFN[u] == Low[u]) {
            scc++;
            do {
                v = Stack[--top];
                Instack[v] = false;
                Belong[v] = scc;
                num[scc]++;
            } while(v != u);
        }
    }
    int main() {
        int n, m;
        scanf("%d%d", &n, &m);
        init();
        for(int i = 0; i < m; i++) {
            int a, b;
            scanf("%d%d", &a, &b);
            if(mmp[a][b] != 1) {
                mmp[a][b] = 1;
                add(a , b);
            }
        }
        memset(DFN, 0, sizeof(DFN));
        memset(Low, 0, sizeof(Low));
        memset(Instack, false, sizeof(Instack));
        memset(num, 0, sizeof(num));
        for(int i = 1; i <= n; i++) {
            if(!DFN[i]) Tarjan(i);
        }
        for(int i = 1; i <= n; i++) {
            for(int j = head[i]; j != -1; j = edge[j].next) {
                int v = edge[j].v;
                if(Belong[i] != Belong[v]) Out[Belong[i]]++;
            }
        }
        int ans = 0 , pos = -1;
        for(int i = 1; i <= scc; i++) {
            if(Out[i] == 0) {ans++, pos = i;}
        }
        if(ans > 1) printf("0
    ");
        else printf("%d
    " , num[pos]);
        return 0;
    }
    
  • 相关阅读:
    zoj 3627#模拟#枚举
    Codeforces 432D Prefixes and Suffixes kmp
    hdu 4778 Gems Fight! 状压dp
    CodeForces 379D 暴力 枚举
    HDU 4022 stl multiset
    手动转一下田神的2048
    【ZOJ】3785 What day is that day? ——KMP 暴力打表找规律
    poj 3254 状压dp
    C++中运算符的优先级
    内存中的数据对齐
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6876856.html
Copyright © 2011-2022 走看看