• POJ 3177 Redundant Paths POJ 3352 Road Construction


    这两题是一样的,代码完全一样。

    就是给了一个连通图,问加多少条边可以变成边双连通。

    去掉桥,其余的连通分支就是边双连通分支了。一个有桥的连通图要变成边双连通图的话,把双连通子图收缩为一个点,形成一颗树。需要加的边为(leaf+1)/2    (leaf为叶子结点个数)

    POJ 3177 给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图。

    参考:http://blog.csdn.net/lyy289065406/article/details/6762432

    http://www.cnblogs.com/kuangbin/p/3184889.html

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <map>
    using namespace std;
    
    const int MAXN = 5010;//点数
    const int MAXM = 20010;//边数,因为是无向图,所以这个值要*2
    
    struct Edge
    {
        int to,next;
        bool cut;//是否是桥标记
    }edge[MAXM];
    int head[MAXN],tot;
    int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~block
    int Index,top;
    int block;//边双连通块数
    bool Instack[MAXN];
    int bridge;//桥的数目
    
    void addedge(int u,int v)
    {
        edge[tot].to = v;edge[tot].next = head[u];edge[tot].cut=false;
        head[u] = 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] > DFN[v] )
                Low[u] = DFN[v];
        }
        if(Low[u] == DFN[u])
        {
            block++;
            do
            {
                v = Stack[--top];
                Instack[v] = false;
                Belong[v] = block;
            }
            while( v!=u );
        }
    }
    void init()
    {
        tot = 0;
        memset(head,-1,sizeof(head));
    }
    
    int du[MAXN];//缩点后形成树,每个点的度数
    void solve(int n)
    {
        memset(DFN,0,sizeof(DFN));
        memset(Instack,false,sizeof(Instack));
        Index = top = block = 0;
        Tarjan(1,0);
        int ans = 0;
        memset(du,0,sizeof(du));
        for(int i = 1;i <= n;i++)
           for(int j = head[i];j != -1;j = edge[j].next)
              if(edge[j].cut)
                 du[Belong[i]]++;
        for(int i = 1;i <= block;i++)
           if(du[i]==1)
              ans++;
        //找叶子结点的个数ans,构造边双连通图需要加边(ans+1)/2
        printf("%d
    ",(ans+1)/2);
    }
    int main()
    {
        int n,m;
        int u,v;
        while(scanf("%d%d",&n,&m)==2)
        {
            init();
            while(m--)
            {
                scanf("%d%d",&u,&v);
                addedge(u,v);
                addedge(v,u);
            }
            solve(n);
        }
        return 0;
    }
  • 相关阅读:
    linux文件属性基础篇
    Linux重定向符号(重点)
    linux---vim和grep
    linux目录文件与系统启动(3)/usr目录、/var目录和/proc目录讲解
    Linux 安装和 连接xshell
    shiro 快速入门详解。
    th 表达式的简单使用。
    springboot 分布式项目,子级项目各自的作用。
    springboot 配置百里香 thymeleaf?
    springboot 配置mybatis 配置mapper.xml
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3184891.html
Copyright © 2020-2023  润新知