hdu-4612-Warm up(边双连通分量--有重边)

题意:有N 个点,M条边,加一条边,求割边最少。(有重边)

分析:先求双连通分量,缩点形成一个生成树,然后求这个的直径,割边-直径即是答案

因为有的图上可能有重边,这样不好处理。我们记录每条边的标号(一条无向边拆成的两条有向边标号相同)这样就能限制不走一样的边而能走重边!

// File Name: 1002.cpp
// Author: Zlbing
// Created Time: 2013年08月02日 星期五 18时16分10秒
#pragma comment(linker,"/STACK:102400000,102400000")
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
#define REP(i,r,n) for(int i=r;i<=n;i++)
#define RREP(i,n,r) for(int i=n;i>=r;i--)
const int MAXN=2e5+100;

int n,m;
struct Edge{
    int u,v;
    Edge(){}
    Edge(int a,int b){
        u=a;
        v=b;
    }
};
vector<Edge> edges;
vector<int> G[MAXN];
vector<int> P[MAXN];
int dfs_clock,bcc_cnt;
int pre[MAXN];
int T[MAXN];
//fa为u的父亲边
//这样标识就可以走重边而不能走父亲边
int dfs1(int u,int fa)
{
    int lowu=pre[u]=++dfs_clock;
    for(int i=0;i<G[u].size();i++)
    {
        int mm=G[u][i];
        int v=edges[mm].v;
        if(fa==(mm^1))continue;
        if(!pre[v])
        {
            int lowv=dfs1(v,mm);
            lowu=min(lowu,lowv);
            if(lowv>pre[u])
            {
                P[v].push_back(u);
                P[u].push_back(v);
            }
        }
        else if(pre[v]<pre[u])
        {
            lowu=min(pre[v],lowu);
        }
    }
    return lowu;
}
void dfs2(int u,int fa)
{
    T[u]=bcc_cnt;
    for(int i=0;i<G[u].size();i++)
    {
        int v=edges[G[u][i]].v;
        bool f=true;
        for(int j=0;j<P[u].size();j++)
        {
            int vv=P[u][j];
            if(v==vv)
            {
                f=false;break;
            }
        }
        if(!f||T[v])continue;
        dfs2(v,u);
    }
}
void find_bcc(int n)
{
     dfs_clock=0,bcc_cnt=0;
    memset(pre,0,sizeof(pre));
    memset(T,0,sizeof(T));
    for(int i=1;i<=n;i++)
        if(!pre[i])
            dfs1(i,-1);
    for(int i=1;i<=n;i++)
        if(!T[i])
        {
            bcc_cnt++;
            dfs2(i,-1);
        }
}
vector<int> GG[MAXN];
int d[MAXN];
void dfs(int u,int dep)
{
    d[u]=dep;
    for(int i=0;i<GG[u].size();i++)
    {
        int v=GG[u][i];
        if(!d[v])
        {
            dfs(v,dep+1);
        }
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n+m==0)break;
        REP(i,0,n){
            G[i].clear();
            P[i].clear();
        }
        edges.clear();
        int a,b;
        REP(i,1,m)
        {
            scanf("%d%d",&a,&b);
            Edge e;
            e=Edge(a,b);
            edges.push_back(e);
            e=Edge(b,a);
            edges.push_back(e);
            int mm=edges.size();
            G[a].push_back(mm-2);
            G[b].push_back(mm-1);
        }
        find_bcc(n);
        REP(i,0,n)
        {
            GG[i].clear();
        }
        /*
        for(int i=1;i<=n;i++)
        {
            printf("T[%d]=%d
",i,T[i]);
        }
        */
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<P[i].size();j++)
            {
                int v=P[i][j];
                if(T[i]!=T[v])
                {
                //    printf("u=%d v=%d
",T[i],T[v]);
                    GG[T[i]].push_back(T[v]);
                }
            }
        }
        CL(d,0);
        dfs(1,1);
        int maxn=0;
        int flag=0;
        for(int i=1;i<=bcc_cnt;i++)
        {
            if(d[i]>maxn)
            {
                maxn=d[i];
                flag=i;
            }
        }
        CL(d,0);
        dfs(flag,1);
        maxn=0;
        for(int i=1;i<=bcc_cnt;i++)
        {
            if(d[i]>maxn)
                maxn=d[i];
        }
    //    printf("bcc_cnt=%d maxn=%d
",bcc_cnt,maxn);
        cout<<bcc_cnt-maxn<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/arbitrary/p/3236092.html