zoukankan      html  css  js  c++  java
  • HDU 2767:Proving Equivalences(强连通)

    题意:

    一个有向图,问最少加几条边,能让它强连通

    方法:

    1:tarjan 缩点

    2:采用如下构造法:

       缩点后的图找到所有头结点和尾结点,那么,可以这么构造:把所有的尾结点连一条边到头结点,就必然可以是强连通了。如果说有几个结点不连通,那么让他们的尾结点相互只向对方的头结点就好了。

    那么,最后的答案就是,头结点和尾结点中比较小的那个数量。

    当然,如果缩点后只有一个点,那么就是0;

    代码:

    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    using namespace std;
    #define N 20010
    using namespace std;
    vector <int> to[N];
    vector <int> g[N];
    int in[N], out[N];
    //#define vii vector<int>iterator;
    int low[N], dep[N], id[N], s[N], top, scnt, cnt;
    int n, m;
    void tarinit() {
        top = cnt = scnt = 0;
        memset(dep, -1, sizeof(dep));
    }
    
    void tarjan(int u) {
        int minc = low[u] = dep[u] = cnt++;
        s[top++] = u;
        int end = to[u].size();
        for (int i = 0; i < end; i++) {
            if (dep[to[u][i]] == -1) tarjan(to[u][i]);
            if (minc > low[to[u][i]]) minc = low[to[u][i]];
        }
        if (minc < low[u]) low[u] = minc;
        else {
            while (s[top] != u){
                id[s[--top]] = scnt;
                low[s[top]] = n+1;
            }
            scnt++;
        }
    }
    
    int main() {
        int t;
        scanf("%d", &t);
        while (t--) {
            scanf("%d%d", &n, &m);
            for (int i = 0; i <= n; i++) to[i].clear(), g[i].clear();
            for (int i = 0; i < m; i++) {
                int u, v;
                scanf("%d%d", &u, &v);
                to[u].push_back(v);
            }
            tarinit();
            for (int i = 1; i <= n; i++) {
                if (dep[i] == -1) {
                    tarjan(i);
                } 
            }
            memset(out,0,sizeof(out));
            memset(in,0,sizeof(in));
            for (int i = 1; i <= n; i++) {
                int end = to[i].size();
                for (int j = 0; j < end; j++) {
                    if (id[i] != id[to[i][j]]) {
                        out[id[i]]++;
                        in[id[to[i][j]]]++;
                    }
                }
            }
            if (scnt == 1)  {
                puts("0");
                continue;
            }
            int root = 0;
            int leaf = 0;
            for (int i = 0; i < scnt; i++) {
                if (out[i] == 0) leaf++;
                if (in[i] == 0) root++;
            }
            printf("%d
    ", max(root,leaf));
        }
        return 0;
    }
  • 相关阅读:
    传递函数笔记
    模糊控制算法详细讲解
    SDRAM学习笔记
    基于STM32的CRC校验说明
    如何把图片设置成24位图/8位图??
    C2MIF软件使用说明
    ROM和RAM的内存详细说明
    Logback配置
    Logback使用
    common-logging源码解析
  • 原文地址:https://www.cnblogs.com/shinecheng/p/3655228.html
Copyright © 2011-2022 走看看