poj 3694 Network

分析:先縮點成樹,然後模擬LCA過程。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 200500;
//const int maxm = 405000;
struct Node{
    int v,next;
}e[maxn*4],tree[maxn*4];
int bridge,vis[maxn],pre[maxn],head[maxn];
int dfn[maxn],low[maxn],head1[maxn],id[maxn],index,top,num,scc,sta[maxn];
void add(int a,int b){
    e[num].v=b;
    e[num].next=head[a];
    head[a]=num++;
}
void add_tree(int a,int b){
    tree[num].v=b;
    tree[num].next=head1[a];
    head1[a]=num++;
}
void init(){
    top=0;
    scc=num=index=0;
    memset(dfn,0,sizeof(dfn));
}
void tarjan(int u,int fa){
    dfn[u]=low[u]=++index;
    sta[++top]=u;
    int cnt=0;
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].v;
        if(!dfn[v]){
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
        }
        else if(fa==v){
            if(cnt) low[u]=min(low[u],dfn[v]);
            cnt++;
        }
        else{
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u]){
        int x;
        scc++;
        do{
            x=sta[top--];
            id[x]=scc;
           // printf("%d ",x);
        }while(x!=u);
      //  printf("\n");
    }
}
int ran[maxn];
void lca_dfs(int u,int dept,int fa){
    ran[u]=dept;
    for(int i=head1[u];i!=-1;i=tree[i].next){
        int v=tree[i].v;
        if(v==fa) continue;
        low[v]=1;
        lca_dfs(v,dept+1,u);
        pre[v]=u;
    }
}
void lca(int u,int v){
    while(ran[u]>ran[v]){
        if(low[u]){
            low[u]=0;
            bridge--;
        }
        u=pre[u];
    }
    while(ran[u]<ran[v]){
        if(low[v]){
            low[v]=0;
            bridge--;
        }
        v=pre[v];
    }
    while(u!=v){
        if(low[u]){
            bridge--;
            low[u]=0;
        }
        if(low[v]){
            bridge--;
            low[v]=0;
        }
        u=pre[u];
        v=pre[v];
    }
}
int main(){
    int n,m,con=1;
    while(~scanf("%d %d",&n,&m) && (n+m)){
        init();
        for(int i=0;i<=n;i++){
            head[i]=-1;
            vis[i]=0;
        }
        for(int i=0;i<m;i++){
            int a,b;
            scanf("%d %d",&a,&b);
            add(a,b);
            add(b,a);
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]){
                tarjan(i,-1);
            }
        }
        num=0;
        for(int i=0;i<=n;i++){
            head1[i]=-1;
            low[i]=0;
        }
        for(int u=1;u<=n;u++){
           // vis[u]=1;
            for(int i=head[u];i!=-1;i=e[i].next){
                int v=e[i].v;
              //  if(vis[v]) continue;
                if(id[u]!=id[v]){
                    add_tree(id[u],id[v]);
                   // printf("link----%d %d\n",id[u],id[v]);
                }
            }
        }
        lca_dfs(1,1,-1);
        bridge=scc-1;
//        for(int i=1;i<=scc;i++){
//            printf("%d---%d\n",i,ran[i]);
//        }
        int q;
        scanf("%d",&q);
        printf("Case %d:\n",con++);
        while(q--){
            int a,b;
            scanf("%d %d",&a,&b);
            if(id[a]!=id[b]){
                lca(id[a],id[b]);
            }
           // else{
                printf("%d\n",bridge);
           // }
        }
       // printf("%d\n",bridge);
//        for(int i=1;i<=n;i++){
//            printf("%d---%d\n",i,id[i]);
//        }
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章