• Luogu P2341 [HAOI2006]受欢迎的牛


    P2341 [HAOI2006]受欢迎的牛

    题目大意

    题面已经说的够明白了

    我只是为了多一个标题,走走过场,好看QwQ

    思路

    题目明确给出的条件足够。既然牛的爱慕关系可以传递,那么自然地就想到了连通分量喽。只要是在同一个连通分量内的牛,它们对整个局面造成的影响是一致的。那么就可以通过Tarjan算法进行缩点。所点后统计每个强连通分量的出度。如果只有一个出度为零的强连通分量(注意是强连通分量),那么这个点就是受欢迎的牛。如果存在两个以上的话,就证明它俩个都没有互相爱慕,那么肯定就不存在受欢迎的牛,所以直接输出0

    吐槽一下

    woc,Tarjan写错了都能刚出85分来,学到了学到了,我之前交的时候++Index写成了Index++。。。遛了遛了

    代码

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <stack>
    
    const int maxnode = 1e4+3;
    const int maxedge = 5e4+3;
    
    using namespace std;
    
    stack<int> S;
    int n, m, first[maxnode], next[maxedge], u[maxedge], v[maxedge], num[maxnode];
    int low[maxnode], dfn[maxnode], Index, cnt, in[maxnode], Indgr[maxnode];
    bool vis[maxnode];
    
    inline int readInt() {
        int x = 0, f = 1;
        char c = getchar();
        while (c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while (c <= '9' && c >= '0') {
            x = x*10 + c-'0';
            c = getchar();
        }
        return x * f;
    }
    
    inline void addedge(int f, int i) {
        next[i] = first[f];
        first[f] = i;
    }
    
    inline void Tarjan(int x) {
        low[x] = dfn[x] = ++Index;
        vis[x] = 1;
        S.push(x);
        int k = first[x];
        while (k != -1) {
            if(!dfn[v[k]]) {
                Tarjan(v[k]);
                low[x] = min(low[x], low[v[k]]);
            }
            else if(vis[v[k]]) {
                low[x] = min(low[x], dfn[v[k]]);
            }
            k = next[k];
        }
        if(dfn[x] == low[x]) {
            cnt++;
            while (!S.empty()) {
                int temp = S.top();
                S.pop();
                vis[temp] = 0;
                in[temp] = cnt;
                num[cnt]++;
                if(temp == x) break;
            }
        }
    }
    
    int main() {
        n = readInt(), m = readInt();
        memset(first, -1, sizeof(first));
        for(int i=1; i<=m; i++) {
            u[i] = readInt(); v[i] = readInt();
            addedge(u[i], i);
        }
        for(int i=1; i<=n; i++) {
            if(!dfn[i]) Tarjan(i);
        }
        for(int i=1; i<=n; i++) {
            int k = first[i];
            while (k != -1) {
                if(in[v[k]] != in[u[k]])
                    Indgr[in[u[k]]]++;
                k = next[k];
            }
        }
        int mark = 0;
        for(int i=1; i<=cnt; i++) {
            if(Indgr[i] == 0) {
                if(mark) {
                    printf("0
    ");
                    return 0;
                }
                mark = i;
            }
        }
        printf("%d", num[mark]);
    }
  • 相关阅读:
    ES6学习--函数剩余参数 (rest参数)
    ES6学习 --函数参数默认值与解构赋值默认值
    ES6学习--Array.from()方法
    02ython基础知识(一)
    01 Python初探
    c#利用IronPython调用python的过程种种问题
    Android 对话框(Dialogs)
    不可不知的安卓屏幕知识
    C#中的Split用法以及详解
    关于XML文档操作类
  • 原文地址:https://www.cnblogs.com/bljfy/p/9326200.html
Copyright © 2020-2023  润新知