POJ 3694

来源:互联网 发布:淘宝代购only哪家靠谱 编辑:程序博客网 时间:2024/06/08 20:55

tarjan求双联通(含重边)+ LCA定义求法


#include<cstdio>#include<cstring>#include<algorithm>#define N 100100#define M 200100using namespace std;int head[N],cnt,num,depth;int dfn[N],low[N],fa[N],Dfn[N];bool yes[N];struct Edge{    int v,next;}edge[M*2];void addedge(int u,int v){    edge[cnt].v=v;    edge[cnt].next=head[u];    head[u]=cnt++;    edge[cnt].v=u;    edge[cnt].next=head[v];    head[v]=cnt++;}void init(){    memset(head,-1,sizeof(head));    memset(dfn,0,sizeof(dfn));    memset(dfn,0,sizeof(dfn));    memset(yes,0,sizeof(yes));    fa[1]=1,dfn[0]=0;    cnt=num=depth=0;}void tarjan(int u,int fat){    int i,flag=1;    dfn[u]=low[u]=++depth;    Dfn[u]=Dfn[fat]+1;    for(i=head[u];i!=-1;i=edge[i].next){        int v=edge[i].v;        if(v==fat && flag){            flag=0;            continue;        }        if(dfn[v]==0){            fa[v]=u;            tarjan(v,u);            low[u]=min(low[u],low[v]);            if(low[v]>dfn[u]){                yes[v]=1;                num++;            }        }        else            low[u]=min(low[u],dfn[v]);    }}void LCA(int u,int v){    if(Dfn[u]<Dfn[v])swap(u,v);    while(Dfn[u]>Dfn[v]){        if(yes[u]){            num--;            yes[u]=0;        }        u=fa[u];    }    while(u!=v){        if(yes[u]){            num--;            yes[u]=0;        }        if(yes[v]){            num--;            yes[v]=0;        }        u=fa[u],v=fa[v];    }}int main(){    int i,n,m,Q;    int u,v;    int cas=0;    while(scanf("%d %d",&n,&m)){        if(n==0 && m==0)break;        init();        for(i=1;i<=m;i++){            scanf("%d %d",&u,&v);            addedge(u,v);        }        tarjan(1,0);        scanf("%d",&Q);        printf("Case %d:\n",++cas);        for(i=1;i<=Q;i++){            scanf("%d %d",&u,&v);            LCA(u,v);            printf("%d\n",num);        }    }    return 0;}