1. 程式人生 > >【無向Tarjan+樹的直徑】HDU

【無向Tarjan+樹的直徑】HDU

題意:

給出一張無向圖,加一條邊,問能使得圖中橋的數量最少是多少。

題解:

無向圖Tarjan縮點,形成一棵樹。樹上的最長鏈加一條邊是最優解。答案就是原本橋的數量減去樹的直徑。

#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
const int M=2e6+7;
const int N=2e5+7;
int n,m,ans;
struct Edge{
    int v,nxt;
    Edge(int v=0,int nxt=0):v(v),nxt(nxt){}
}edge[M],e[M];

int p[N],edn;
void add(int u,int v){
    edge[++edn]=Edge(v,p[u]);p[u]=edn;
    edge[++edn]=Edge(u,p[v]);p[v]=edn;
}

int dfn[N],low[N],bcc[N],bccnum,index,st[N],top;
bool ef[M];
void tarjan(int u){
    dfn[u]=low[u]=++index;
    st[++top]=u;
    for(int i=p[u];~i;i=edge[i].nxt){
        int v=edge[i].v;
        if(ef[i]) continue;
        ef[i]=ef[i^1]=1;
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
            /*if(dfn[u]<low[v]){
                ef[i]=ef[i^1]=2;
            }*/
        }
        else low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u]){
        bccnum++;
        while(1){
            int x=st[top--];
            bcc[x]=bccnum;
            if(x==u) break;
        }
    }
}

int hd[N],ed;
void ad(int u,int v){
    e[++ed]=Edge(v,hd[u]);hd[u]=ed;
    //e[++ed]=Edge(u,hd[v]);hd[v]=ed;
}

void rebuild(){
    memset(hd,-1,sizeof(hd));ed=-1;
    for(int x=1;x<=n;x++){
        int u=bcc[x];
        for(int i=p[x];~i;i=edge[i].nxt){
            int v=bcc[edge[i].v];
            if(u==v) continue;
            ad(u,v);
        }
    }
}

void init(){
    memset(bcc,0,sizeof(bcc));bccnum=0;
    memset(p,-1,sizeof(p));edn=-1;
    memset(dfn,0,sizeof(dfn));
    memset(ef,false,sizeof(ef));
    top=index=ans=0;
}
typedef struct Node{
    int id,stp;
    Node(int id=0,int stp=0):id(id),stp(stp){}
};
bool vis[N];
Node bfs(int x){
    memset(vis,0,sizeof(vis));
    queue<Node>q;
    q.push(Node(x,0));vis[x]=true;
    Node t;
    while(!q.empty()){
        t=q.front();q.pop();
        int u=t.id;
        for(int i=hd[u];~i;i=e[i].nxt){
            int v=e[i].v;
            if(vis[v]) continue;
            vis[v]=true;
            q.push(Node(v,t.stp+1));
        }
    }
    return t;
}

int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0&&m==0) break;
        init();
        int u,v;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        int ans=0;
        for(int i=1;i<=n;i++){
            if(!bcc[i]) tarjan(i);
        }
        rebuild();
        Node x=bfs(1);
        Node y=bfs(x.id);
        printf("%d\n",bccnum-1-y.stp);
    }
}