POJ3694 Network 割边+LCA

来源:互联网 发布:最好的视频软件 编辑:程序博客网 时间:2024/05/02 06:07

题目链接:

Poj3694



题意:

给出一个N(1 ≤ N ≤ 100,000)个点 和 M(N - 1 ≤ M ≤ 200,000)的连通图.

有Q ( 1 ≤ Q ≤ 1,000)个询问 每次询问增加一条边(累加下去)

输出每增加一条边后剩下的桥的数量




题解:

10W点加1000次询问 每次询问都用Tarjin算法求一次肯定会超时的

考虑  每次加一条边a-b的实质:

从a到b的路径中的所有割边都将消失

那如何记录这条路径呢

在Tarjan算法递归的过程中通过树边建立一棵树 

然后每次询问分别从a  b开始 一直到它们的最近公共祖先 出现的割边全部消失即可


代码:


#include<iostream>#include<cstdio>#include<cstring>#include<vector>#define maxn 100050using namespace std;struct node{    int to,next;}edge[maxn*4];int head[maxn];int s;int dfn[maxn],low[maxn],num;int level[maxn],fa[maxn];int flag[maxn];int n,ans;void init(){    memset(head,-1,sizeof(head));    memset(dfn,0,sizeof(dfn));    memset(flag,0,sizeof(flag));    s=ans=num=0;    level[0]=0;    for(int i=1;i<=n;i++)        fa[i]=i;}void addedge(int a,int b){    edge[s]={b,head[a]};    head[a]=s++;}void lca(int a,int b){    while(level[b]>level[a])    {        if(flag[b])            ans--,flag[b]=0;        b=fa[b];    }    while(level[a]>level[b])    {        if(flag[a])            ans--,flag[a]=0;        a=fa[a];    }    while(a!=b)    {        if(flag[a])            ans--,flag[a]=0;        if(flag[b])            ans--,flag[b]=0;        a=fa[a],b=fa[b];    }}void Tarjan(int u,int pre){    dfn[u]=low[u]=++num;    level[u]=level[pre]+1;              //建树    for(int i=head[u];i!=-1;i=edge[i].next)    {        int v=edge[i].to;        if(!dfn[v])        {            fa[v]=u;            Tarjan(v,u);            low[u]=min(low[u],low[v]);            if(dfn[u]<low[v])         //标记割边                flag[v]=1,ans++;        }        if(v!=pre)            low[u]=min(low[u],dfn[v]);    }}int main(){    int m,a,b;    int Case=1;    while(scanf("%d%d",&n,&m)&&(n+m))    {        init();        while(m--)        {            scanf("%d%d",&a,&b);            addedge(a,b);            addedge(b,a);        }        Tarjan(1,0);        scanf("%d",&m);        printf("Case %d:\n",Case++);        while(m--)        {            scanf("%d%d",&a,&b);            if(ans!=0)                lca(a,b);            printf("%d\n",ans);        }        printf("\n");    }    return 0;}

0 0
原创粉丝点击