poj 3177Redundant Paths(边双连通分支)

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

题意:给出一个n个点,m条边的连通图,问至少加几条边使两两点可以至少两条路到达。

思路:题目就是要将一个有桥的连通图变成双连通图。   

把双连通子图缩点,形成一颗树。假设树的叶子节点有leaf个,至少要加的边数就是(leaf+1)/2。

为什么是(leaf+1)/2?只要两两叶子成对相连即可。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=5500;
const int maxm=20050;
struct node{
    int u,v,w,nxt,cut;
}e[maxm];
int h[maxn],dfn[maxn],low[maxn],st[maxn],vis[maxn];
int du[maxn],belong[maxn],num,cnt,tot,top,ans,n,m; 

void add(int u,int v)
{
    e[cnt].u=u;
    e[cnt].v=v;
    e[cnt].cut=0;
    e[cnt].nxt=h[u];
    h[u]=cnt++;
}

void tarjan(int u,int pre)
{
    dfn[u]=low[u]=++tot;
    vis[u]=1; 
    st[++top]=u;
    int pre_cnt=0; 
    for(int i=h[u];i!=-1;i=e[i].nxt)
    {
        int v=e[i].v;
        if(v==pre&&pre_cnt==0)    
        {
            pre_cnt++;
            continue;
        }
        if(!dfn[v]) 
        {
            tarjan(v,u); 
            low[u]=min(low[u],low[v]);  
            if(low[v]>dfn[u])//
            {
                e[i].cut=1;
                e[i^1].cut=1;
            }  
        }
        else if(vis[v]) 
            low[u]=min(low[u],dfn[v]);
    }
    
    if(dfn[u]==low[u]) 
    {
        int t;
        num++; 
        do{
            t=st[top--]; 
            vis[t]=0; 
            belong[t]=num; 
        }while(t!=u);
    }
}
int main()
{
    int u,v;
    cnt=top=tot=ans=0;
    memset(h,-1,sizeof(h));
    memset(du,0,sizeof(du));
    memset(dfn,0,sizeof(dfn));
    memset(vis,0,sizeof(vis));
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    tarjan(1,0); 
    for(int i=1;i<=n;i++)
    {
        for(int j=h[i];j!=-1;j=e[j].nxt)
        {
            if(e[j].cut)
                du[belong[i]]++;
        }
    }
    for(int i=1;i<=num;i++)
    {
        //cout<<i<<' '<<du[i]<<endl;
        if(du[i]==1)
            ans++;
    }    
    printf("%d\n",(ans+1)/2);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xiongtao/p/11250379.html
今日推荐