zoukankan      html  css  js  c++  java
  • POJ 3177 Redundant Paths 边双连通分支

    题目链接:http://poj.org/problem?id=3177

    题目大意是 给一个无向图,求至少要添加多少条边才能使其变为边双连通图

    边双连通图简单来说就是联通且没有割边(桥)

    图是连通的,并且没有给重边(所以程序中没有处理重边)

    思想是缩环,然后统计有多少个叶子节点,答案为(叶子节点数目+1)/ 2

    统计叶子的过程是先找出所有的割边

    然后逐个遍历点,遍历边,若边是割边则去点所在的scc的度数加一

    这样到最后度数为1的scc就是叶子

    完全参考自kuangbin模板

    #include <cstdio>
    #include <cstdlib>
    #include <ctime>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <set>
    #include <queue>
    #include <vector>
    #include <ctime>
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> P;
    
    template<class T>
    inline bool read(T &n)
    {
        T x = 0, tmp = 1;
        char c = getchar();
        while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
        if(c == EOF) return false;
        if(c == '-') c = getchar(), tmp = -1;
        while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
        n = x*tmp;
        return true;
    }
    
    template <class T>
    inline void write(T n)
    {
        if(n < 0)
        {
            putchar('-');
            n = -n;
        }
        int len = 0,data[20];
        while(n)
        {
            data[len++] = n%10;
            n /= 10;
        }
        if(!len) data[len++] = 0;
        while(len--) putchar(data[len]+48);
    }
    //-----------------------------------
    
    const int maxn = 5010;
    const int maxm = 20010;
    struct Edge
    {
        int to, next;
        bool cut;
    }edge[maxm];
    
    int head[maxn], tot;
    int Low[maxn], DFN[maxn], Stack[maxn], Belong[maxn];
    int Index, top;
    int scc;
    int bridge;
    bool Instack[maxn];
    int num[maxn];
    
    void addedge(int u, int v)
    {
        edge[tot].to = v;
        edge[tot].next = head[u];
        edge[tot].cut = false;
        head[u] = tot++;
        edge[tot].to = u;
        edge[tot].next = head[v];
        edge[tot].cut = false;
        head[v] = tot++;
    }
    
    void Tarjan(int u, int pre)
    {
        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].to;
            if(v == pre)
                continue;
            if(!DFN[v])
            {
                Tarjan(v, u);
                if(Low[u] > Low[v])
                    Low[u] = Low[v];
                if(Low[v] > DFN[u])
                {
                    bridge++;
                    edge[i].cut = true;
                    edge[i^1].cut = true;
                }
            }
            else if(Instack[v] && Low[u] > Low[v])
                Low[u] = Low[v];
        }
        if(Low[u] == DFN[u])
        {
            scc++;
            do
            {
                v = Stack[--top];
                Instack[v] = false;
                Belong[v] = scc;
                num[scc]++;
            }
            while(v != u);
        }
    }
    
    int du[maxn];
    
    void solve(int N)
    {
        memset(DFN, 0, sizeof(DFN));
        memset(Instack, 0, sizeof(Instack));
        memset(num, 0, sizeof(num));
        Index = scc = top = 0;
        for(int i = 1; i <= N; i++)
        {
            if(!DFN[i])
                Tarjan(i, 0);
        }
    
        for(int i = 1; i <= N; i++)
        {
            for(int j = head[i]; j != -1; j = edge[j].next)
            {
                if(edge[j].cut) //若为桥,则去点所在的scc的度+1
                    du[Belong[edge[j].to]]++;
            }
        }
    
        int leaf = 0;
        for(int i = 1; i <= scc; i++)   //找“叶子” 即度为1的节点
        {
            if(du[i] == 1)
                leaf++;
        }
    
        printf("%d
    ", (leaf + 1)/ 2);
    }
    
    void init()
    {
        tot = 0;
        bridge = 0;
        memset(head, -1, sizeof(head));
    }
    
    int main()
    {
        //freopen("in.txt", "r", stdin);
    
        int F, R;
        scanf("%d%d", &F, &R);
    
        init();
        for(int i = 0; i < R; i++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            addedge(u, v);
        }
    
        solve(F);
    
        return 0;
    }
  • 相关阅读:
    无声的吐槽csdn
    成长
    最近忙的头发都油油的
    pycharm5工具免费分享及安装教程
    分布式版本控制git常见问题之gitignore冲突
    感觉自己还是太年轻,还有很多东西不会
    关于laravel5.2仓库的建立,以及简单调用
    乎,前所未有的挑战!
    嘿嘿,无聊的时候,来点好玩的,翻滚吧,杀马特!!!
    随便说说
  • 原文地址:https://www.cnblogs.com/dishu/p/4517670.html
Copyright © 2011-2022 走看看