zoukankan      html  css  js  c++  java
  • POJ

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

    2、POJ - 3177 Redundant Paths(边双连通分支)(模板)  与这道题一模一样。代码就改了下范围,其他都没动。。。

    3、

    //边双连通分支
    /*
    去掉桥,其余的连通分支就是边双连通分支了。一个有桥的连通图要变成边双连通图的话,
    把双连通子图收缩为一个点,形成一颗树。需要加的边为(leaf+1)/2(leaf为叶子结点的个数)
    POJ 3177 给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图。
    */
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    
    const int MAXN=1024;//点数
    const int MAXM=2010;//边数,因为是无向图,所以这个值要 *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;
    }
    View Code
  • 相关阅读:
    网上图书商城-毕业设计
    房屋租赁系统2-毕业设计
    编译解释器-课程设计
    教师学生作业设计-课程设计
    学校论坛系统-毕业设计
    报刊征订系统-毕业设计
    公司内部管理系统-毕业设计
    销售管理系统-毕业设计
    房屋租赁系统-毕业设计
    【日拱一卒】链表——如何实现lru
  • 原文地址:https://www.cnblogs.com/gongpixin/p/5003467.html
Copyright © 2011-2022 走看看