poj 3694 Network 连通分量+LCA

来源:互联网 发布:哈萨维诺亚知乎 编辑:程序博客网 时间:2024/06/01 08:50
#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;const int MAXN=100000+10;const int MAXM=400000+10;struct Edge{    int to,next,cut;} edge[MAXM],edge2[MAXM];int head[MAXN],tot,low[MAXN],dfn[MAXN],pre[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组是连通块的序号int index,top,head2[MAXN],tot2;int block;int instack[MAXN];int bridge;void addedge(int u,int v){    edge[tot].to=v;    edge[tot].next=head[u];    edge[tot].cut=0;    head[u]=tot++;}void addedge2(int u,int v){    edge2[tot2].to=v;    edge2[tot2].next=head2[u];    edge2[tot2].cut=0;    head2[u]=tot2++;}void Tarjan(int u,int pre){    int v;    low[u]=dfn[u]=++index;    Stack[top++]=u;    instack[u]=1;    for(int i=head[u]; i!=-1; i=edge[i].next)    {        v=edge[i].to;        if(v==pre) continue;        if(!dfn[v])        {            Tarjan(v,u);            if(low[u]>low[v]) low[u]=low[v];            if(low[v]>dfn[u])            {                bridge++;                edge[i].cut=1;                edge[i^1].cut=1;            }        }        else if(instack[v]&&low[u]>dfn[v])            low[u]=dfn[v];    }    if(low[u]==dfn[u])    {        block++;        do        {            v=Stack[--top];            instack[v]=0;            Belong[v]=block;        }        while(v!=u);    }}void init(){    tot2=tot=0;    memset(head,-1,sizeof(head));    memset(head2,-1,sizeof(head2));}int father[MAXN];int deep[MAXN];int Find(int x){    if(father[x]==x) return x;    else        return father[x]=Find(father[x]);}void dfs(int u,int d){    for(int i=head2[u]; i!=-1; i=edge2[i].next)    {        int v=edge2[i].to;        if(deep[v]==0)        {            pre[v]=u;            deep[v]=d;            dfs(v,d+1);        }    }}void solve(int n){    memset(dfn,0,sizeof(dfn));    memset(instack,0,sizeof(instack));    bridge=index=top=block=0;    Tarjan(1,0);    int i,j;    for(i=1; i<=n; i++)        for(j=head[i]; j!=-1; j=edge[j].next)        {            if(edge[j].cut==1)                addedge2(Belong[i],Belong[edge[j].to]);        }    for(i=0; i<=n; i++)        father[i]=i;    memset(deep,0,sizeof(deep));    pre[1]=0;    deep[1]=1;    dfs(1,2);}int LCA(int u,int v){    while(u!=v)    {        if(deep[u]>deep[v])            u=pre[u];        else if(deep[u]<deep[v])            v=pre[v];        else        {            u=pre[u];            v=pre[v];        }        u=Find(u);        v=Find(v);    }    return u;}int main(){    int n,m,ans;    int u,v,_=0;    while(scanf("%d%d",&n,&m))    {        if(n==0&&m==0) break;        init();        while(m--)        {            scanf("%d%d",&u,&v);            addedge(u,v);            addedge(v,u);        }        solve(n);        scanf("%d",&m);        printf("Case %d:\n",++_);        while(m--)        {            scanf("%d%d",&u,&v);            u=Belong[u];            v=Belong[v];            if(u==v)            {                printf("%d\n",bridge);                continue;            }            u=Find(u);            v=Find(v);            int lca=LCA(u,v);            ans=0;            while(u!=lca)            {                ans++;                father[u]=lca;                u=pre[u];                u=Find(u);            }            while(v!=lca)            {                ans++;                father[v]=lca;                v=pre[v];                v=Find(v);            }            bridge-=ans;            printf("%d\n",bridge);        }        printf("\n");    }    return 0;}
0 0