Network(poj 3694)

题意:一个无向图可以有重边,下面q个操作,每次在两个点间连接一条有向边,每次连接后整个无向图还剩下多少桥(注意是要考虑之前连了的边,每次回答是在上一次的基础之上)

/*
  tarjan+LCA
  先用tarjan缩点,那么这个图就会变成一棵树,当我们连起不在同一节点时,就相当于
  把树上的两个节点连了起来,这两个节点同他们的公共祖先会形成一个新的缩点,每次统计
  桥的个数。 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define M 200010
using namespace std;
int n,m,num,head[M],low[M],dfn[M],topt;
int s[M],top,f[M],sum,belong[M],cnt,cas;
int Num,Head[M],fa[M],c[M],vis[M];
struct node{int v,pre;}e[M*2];
struct Node{int v,pre;}E[M*2];
void Add(int from,int to)
{
    e[num].v=to;
    e[num].pre=head[from];
    head[from]=num++;
}
void add(int from,int to)
{
    E[Num].v=to;
    E[Num].pre=Head[from];
    Head[from]=Num++;
}
void Tarjan(int x,int fa)
{
    low[x]=dfn[x]=++topt;
    s[++top]=x;f[x]=1;
    for(int i=head[x];i!=-1;i=e[i].pre)
    {
        int v=e[i].v;
        if(i==(fa^1))continue;
        if(dfn[v]==0)
        {
            Tarjan(v,i);low[x]=min(low[x],low[v]);
        }
        else if(f[v])low[x]=min(low[x],dfn[v]);
    }
    if(low[x]==dfn[x])
    {
        sum++;
        while(x!=s[top])
        {
            f[s[top]]=0;belong[s[top]]=sum;top--;
        }
        f[s[top]]=0;belong[s[top]]=sum;top--;
    }
}
void Dfs(int now,int from,int dep)
{
    fa[now]=from;c[now]=dep;
    for(int i=Head[now];i!=-1;i=E[i].pre)
      if(E[i].v!=from)
        Dfs(E[i].v,now,dep+1);
}
void LCA(int a,int b)
{
    if(c[a]<c[b])swap(a,b);
    int t=c[a]-c[b];
    for(int i=1;i<=t;i++)
    {
        if(vis[a]==0)cnt--;
        vis[a]=1;a=fa[a];
    }
    while(a!=b)
    {
        if(vis[a]==0)cnt--;
        vis[a]=1;a=fa[a];
        if(vis[b]==0)cnt--;
        vis[b]=1;b=fa[b];
    }
}
int main()
{
    while(1)
    {
        scanf("%d%d",&n,&m);
        if(n==0&&m==0)break;
        memset(head,-1,sizeof(head));
        memset(Head,-1,sizeof(Head));
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        memset(f,0,sizeof(f));
        memset(belong,0,sizeof(belong));
        memset(vis,0,sizeof(vis));
        memset(c,0,sizeof(c));
        memset(fa,0,sizeof(fa));
        memset(s,0,sizeof(s));
        Num=num=topt=sum=0;
        int u,v;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            Add(u,v);Add(v,u);
        }
        for(int i=1;i<=n;i++)
          if(dfn[i]==0)
            Tarjan(i,-1);
        for(int u=1;u<=n;u++)
          for(int i=head[u];i!=-1;i=e[i].pre)
            if(belong[u]!=belong[e[i].v])
              add(belong[u],belong[e[i].v]);
        Dfs(1,1,0);cnt=sum-1;
        scanf("%d",&m);
        printf("Case %d:\n",++cas);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            int U=belong[u];
            int V=belong[v];
            if(U==V)
            {
                printf("%d\n",cnt);continue;
            }
            LCA(U,V);
            printf("%d\n",cnt);
        }
    }
    return 0;
}
View Code

 

posted @ 2016-08-24 11:00  karles~  阅读(248)  评论(0编辑  收藏  举报