HDU4612 Warm up 边双(重边)缩点+树的直径

题意:一个连通无向图,问你增加一条边后,让原图桥边最少

分析:先边双缩点,因为连通,所以消环变树,每一个树边都是桥,现在让你增加一条边,让桥变少(即形成环)

        所以我们选择一条树上最长的路径,连接两端,这样减少的桥边,最多,所以就是求树的直径

注:这题有重边,所以边双缩点也需要用重边版的

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <vector>
#include <stack>
using namespace std;
typedef long long LL;
const int N = 2e5+5;
int head[N],tot,n,cnt,m,x[N*10],y[N*10];
struct Edge{
   int v,next;
}edge[N*10];
void add(int u,int v){
   edge[tot].v=v;
   edge[tot].next=head[u];
   head[u]=tot++;
}
int dfn[N],low[N],clk,bel[N],d[N];
stack<int>s;
void targin(int u,int f){
   dfn[u]=low[u]=++clk;
   s.push(u);
   bool flag=0;//判断重边
   for(int i=head[u];~i;i=edge[i].next){
       int v=edge[i].v;
       if(v==f&&!flag){
        flag=1;//记录重边出现次数,只跳过父边第一次出现
        continue;
       }
       if(!dfn[v]){
         targin(v,u);
         low[u]=min(low[u],low[v]);
       }
       else if(dfn[v]<low[u])low[u]=dfn[v];
   }
   if(dfn[u]==low[u]){
     ++cnt;
     int k;
     do{
        k=s.top();
        s.pop();
        bel[k]=cnt; 
     }while(k!=u);
   }
}
int S,tmp,ans;
void dfs1(int u,int f){
    d[u]=d[f]+1;
    if(d[u]>tmp){
      tmp=d[u];
      S=u;
    }
    for(int i=head[u];~i;i=edge[i].next){
        int v=edge[i].v;
        if(v==f)continue;
        dfs1(v,u);
    }
}
void dfs2(int u,int f){
    d[u]=d[f]+1;
    ans=max(ans,d[u]);
    for(int i=head[u];~i;i=edge[i].next){
        int v=edge[i].v;
        if(v==f)continue;
        dfs2(v,u);
    }
}
int main(){
    d[0]=-1;
    while(~scanf("%d%d",&n,&m)){
       if(!n&&!m)break;     
       for(int i=1;i<=n;++i){
         head[i]=-1;
         dfn[i]=low[i]=0;
       }
       cnt=clk=tot=0;
       for(int i=1;i<=m;++i){
        scanf("%d%d",&x[i],&y[i]);
        add(x[i],y[i]),add(y[i],x[i]);
       }
       targin(1,-1);
       if(cnt<=2){
        printf("0
");
        continue;
       }
       for(int i=1;i<=cnt;++i)head[i]=-1;
       tot=0;
       for(int i=1;i<=m;++i){
        int k1=bel[x[i]],k2=bel[y[i]];
        if(k1==k2)continue;
        add(k1,k2),add(k2,k1);
       }
       tmp=ans=0;
       dfs1(1,0);
       dfs2(S,0);
       printf("%d
",cnt-1-ans);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuguangzw/p/5489638.html