zoukankan      html  css  js  c++  java
  • hdu_2767,加边至强连通

    http://acm.hdu.edu.cn/showproblem.php?pid=2767

    今天在做图论专题的时候碰到了这题,这样的话,正好学习了来写篇博客吧

    题目意思就是,给你一个有向网络图,问,至少加多少条边能使这个图成强连通

    那么就是要,先把图跑一遍targan,如果这个图是强连通,那么就输出0了,否则缩点,然后求所有点入度为0和出度为0个数的最大值了

    主要理解的地方就是缩点的那个地方,要理解belong数组的含义,以及为什么是求入度0和出席0的最大值

    证明我是不知道= =,真的是只能意会么 ?

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int maxn(55555);
    int low[maxn], dfn[maxn], vis[maxn], belong[maxn];
    struct Edge{
        int v, next;
    }e[maxn];
    int head[maxn], cnt;
    int n, m;
    int step, color;
    int stack[maxn], top;
    void targan(int u){
        low[u] = dfn[u] = ++ step;
        vis[u] = 1;
        stack[top++] = u;
        for(int i = head[u]; i + 1; i = e[i].next){
            int v = e[i].v;
            //printf("--  %d %d\n", u, v);
            if(!dfn[v]){
                targan(v);
                low[u] = min(low[u], low[v]);
            }else if(vis[v])
              low[u] = min(low[u], dfn[v]);
        }
        if(dfn[u] == low[u]){
            color ++;
            int s;
            do{
                s = stack[--top];
                vis[s] = 0;
                belong[s] = color;
            }while(u != s);
        }
    }
    int in[maxn], out[maxn];
    #define clr(a) memset(a, 0, sizeof a)
    void init(){
        clr(dfn);
        clr(vis);
        clr(low);
        clr(belong);
        clr(in);
        clr(out);
        top = step = color = cnt = 0;
        memset(head, -1, sizeof head);
    }
    void add_Edge(int u, int v){
        e[cnt].v = v, e[cnt].next = head[u];
        head[u] = cnt ++;
    }
    void solve(){
        for(int i = 1; i <= n; i ++) if(!dfn[i]) targan(i);
        if(color == 1){
            puts("0");
            return;
        }
        for(int i = 1; i <= n; i ++){
            for(int j = head[i]; j + 1; j = e[j].next){
                int v = e[j].v;
                if(belong[i] != belong[v]){
                    in[belong[v]]++;
                    out[belong[i]] ++;
                }
            }
        }
        int a = 0, b = 0;
        for(int i = 1; i <= color; i ++){
            if(in[i] == 0) a ++;
            if(out[i] == 0) b ++;
        }
        printf("%d\n", max(a, b));
    }
    int main(){
        int tcase;
        scanf("%d", &tcase);
        while(tcase --){
            scanf("%d%d", &n, &m);
            if(m == 0){
                printf("%d\n", n);
                continue;
            }
            init();
            while(m--){
                int u, v;
                scanf("%d%d", &u, &v);
                add_Edge(u, v);
            }
            solve();
        }
        return 0;
    }
  • 相关阅读:
    vs2005 配置winpcap
    qt 解决中文乱码问题
    [翻译] QT正则表达式
    使用QSetting 读写ini文件
    [转]GNOME快捷键
    华为面试题之大整数相加
    qt 程序windows 上发布
    win7英文版中文乱码问题
    CURL命令 Alex
    Sendfile机制 Alex
  • 原文地址:https://www.cnblogs.com/louzhang/p/2646316.html
Copyright © 2011-2022 走看看