zoukankan      html  css  js  c++  java
  • hdu 2767 Proving Equivalences(tarjan缩点)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2767

    题意:问最少加多少边可以让所有点都相互连通。

    题解:如果强连通分量就1个直接输出0,否者输出入度为0的缩点,出度为0的缩点和的最大值

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    const int N = 2e4 + 10;
    const int M = 5e4 + 10;
    struct Edge {
        int v, next;
    }edge[M];
    int head[N], e;
    int Low[N], DFN[N], Belong[N], num[N], Stack[N];
    int Index, top, scc;
    int In[N], 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(Low[u] == DFN[u]) {
            scc++;
            do {
                v = Stack[--top];
                Instack[v] = false;
                Belong[v] = scc;
                num[scc]++;
            } while(v != u);
        }
    }
    int main() {
        int t;
        scanf("%d", &t);
        while(t--) {
            int n, m;
            scanf("%d%d", &n, &m);
            init();
            for(int i = 0; i < m; i++) {
                int s1, s2;
                scanf("%d%d", &s1, &s2);
                add(s1, s2);
            }
            memset(DFN, 0, sizeof(DFN));
            memset(Instack, false, sizeof(Instack));
            memset(Belong, 0, sizeof(Belong));
            memset(num, 0, sizeof(num));
            memset(In, 0, sizeof(In));
            memset(Out, 0, sizeof(Out));
            scc = 0, Index = 0, top = 0;
            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]) {In[Belong[v]]++, Out[Belong[i]]++;}
                }
            }
            int mxin = 0, mxout = 0;
            for(int i = 1; i <= scc; i++) {
                if(In[i] == 0) mxin++;
                if(Out[i] == 0) mxout++;
            }
            if(scc == 1) printf("0
    ");
            else printf("%d
    ", max(mxin, mxout));
        }
        return 0;
    }
    
  • 相关阅读:
    Java--泛型
    Java--文档注释
    Java--网络编程
    Java--序列化
    Java--多线程编程
    Java--ConcurrentHashMap原理分析
    HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别
    面向接口编程详解
    面向接口编程
    base64 数据加密
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6877107.html
Copyright © 2011-2022 走看看