hdu 4612

有一個無向圖,問加一條邊以後最少還有多少個橋。
就是求多少可以消除多少個橋,可知答案就是縮點以後樹的直徑。
求樹的直徑用dfs TLE, bfs就AC了,學到了。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
const int N = 200000 + 10;
const int M = 1000000 + 10;

int cnt[2],to[M*2][2],nt[M*2][2],h[N][2];
int n,m,a,b,top,stk[N],dfn[N],low[N],dfs_clock;
int bc,bcc[N],d[N],vis[N],s,mam;

void add(int u,int v,int idx){
    to[++cnt[idx]][idx] = v;
    nt[cnt[idx]][idx] = h[u][idx];
    h[u][idx] = cnt[idx];
}
void bfs(int root){
    memset(vis,0,sizeof(vis));
    queue<int> Q;
    vis[root] = 1;
    d[root] = 1;
    Q.push(root);
    while(!Q.empty()){
        int u = Q.front();Q.pop();
        for(int i = h[u][1] ; i ; i = nt[i][1]){
            int v = to[i][1];
            if(!vis[v]){
                d[v] = d[u] + 1;
                if(d[v] > mam) mam = d[v] , s = v;
                vis[v] = 1;
                Q.push(v);
            }
        }
    }
}
void tarjan(int u,int fa){
    low[u] = dfn[u] = ++ dfs_clock;
    stk[++top] = u; 
    int mul = 0 ;
    for(int i = h[u][0] ; i ; i = nt[i][0]){
        int v = to[i][0];
        if(v == fa && !mul){
            mul ++ ; continue;
        }
        if(!dfn[v]){
            tarjan(v, u);
            low[u] = min(low[u] , low[v]);
        }
        else if(!bcc[v]) low[u] = min(low[u] , dfn[v]);
    }
    if(low[u] == dfn[u]) {
        bc++;
        while(1){
            int t = stk[top--];
            bcc[t] = bc;
            if(u == t) break;
        }
    }
}
int main(){
    freopen("data.in","r",stdin);
    while(scanf("%d%d",&n,&m) && (m + n)){
        memset(h,0,sizeof(h));
        memset(cnt,0,sizeof(cnt));
        memset(dfn,0,sizeof(dfn));
        memset(bcc,0,sizeof(bcc));
        top = dfs_clock = bc = 0;mam = -1;
        for(int i = 0 ; i < m ;i ++) {
            scanf("%d%d",&a,&b);
            add(a,b,0);
            add(b,a,0);
        }
        for(int i = 1; i <= n ;i ++) 
            if(!dfn[i]) tarjan(i,-1);
        //for(int i = 1; i <= n ;i++) cout<<dfn[i]<<' ';cout<<endl;
		//for(int i = 1; i <= n; i++) cout<<low[i]<<' ';cout<<endl;
		//for(int i = 1; i <= n; i++) cout<<bcc[i]<<' ';cout<<endl;
        for(int i = 1; i <= n ;i ++){
            for(int j = h[i][0] ; j ;j = nt[j][0]){
                int v = to[j][0];
                if(bcc[i] == bcc[v]) continue;
                add(bcc[i],bcc[v],1);
                add(bcc[v],bcc[i],1);
            }
        }
        if(bc == 1) {
            printf("0\n");
            continue;
        }
        bfs(1);
        mam = -1;
        bfs(s);
        printf("%d\n",bc-mam);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章