POJ 3694 Network【LCA】

题意: 给定一个无向图,图中存在一些桥,之后向图中加入Q条边,问每次加入这条边后图中剩下的桥的数量。

分析: 首先对无向图求割边,并进行缩点,使之成为一棵树,这棵树上的所有边都是割边,之后对于每次询问,会连接树上的两个节点,如果这两个节点之间的边与这条边形成一个环,那么这些边就不再是割边,对于缩点后的树,先随意定出一个根,之后对每个节点记录他的父节点,以及他在这棵树中的深度,之后对于每次询问只要从叶子节点一直搜到他们的lca,把路径上的割边去掉。

 

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define maxn 200005
#define max(a,b)(a)>(b)?(a):(b)
#define min(a,b)(a)<(b)?(a):(b)
#define clr(x)memset(x,0,sizeof(x))
struct node
{
    int to,next;
}e[600005];
int tot;
int head[maxn];
void add(int s,int u)
{
    e[tot].to=u;
    e[tot].next=head[s];
    head[s]=tot++;
}
int ti;
int num;
int dfn[maxn],low[maxn];
int br[maxn];
int f[maxn];
int ins[maxn];
void tarjan(int p,int u)
{
    dfn[u]=low[u]=++ti;
    ins[u]=1;
    int i,k;
    for(i=head[u];i;i=e[i].next)
    {
        k=e[i].to;
        if(k==p)
            continue;
        if(ins[k])
            low[u]=min(low[u],dfn[k]);
        else 
        {
            f[k]=u;
            tarjan(u,k);
            low[u]=min(low[u],low[k]);
            if(low[k]>dfn[u])
            {
                br[k]=1;
                num++;
            }
        }
    }
}
int sta[maxn];
int top;
void LCA(int x,int y)
{
    sta[0]=x;
    sta[1]=y;
    top=2;
    while(x!=y)
    {
        if(dfn[x]>dfn[y]){
            if(br[x])
            {
                num--;
                br[x]=0;
            }
            sta[top++]=(x=f[x]);
        }
        else if(dfn[x]<dfn[y])
        {
            if(br[y])
            {
                num--;
                br[y]=0;
            }
            sta[top++]=(y=f[y]);
        }
    }
    while(top--)
        if(sta[top]!=x)
            f[sta[top]]=x;
}
int main()
{
    int n,m,a,b,ca=1;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)
            break;
        tot=1; ti=0; num=0; 
        clr(head); clr(br); clr(ins); 
        while(m--)
        {
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        f[1]=1;
        tarjan(0,1);
        printf("Case %d:\n",ca++);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d",&a,&b);
            LCA(a,b);
            printf("%d\n",num);
        }
        printf("\n");
    }
    return 0;
}

 

 

posted @ 2012-08-04 00:48  'wind  阅读(217)  评论(0编辑  收藏  举报