• 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
  • 相关阅读:
    awk例子
    vsftp搭建
    makefile里PHONY的相关介绍
    youget帮助使用手册
    正则表达式全集
    常用的正则表达式
    基本用法
    心情
    asp.net和java
    java and asp.net
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5489638.html
Copyright © 2020-2023  润新知