当前位置: 代码迷 >> 综合 >> poj-3694-Network-并查集+tarjan
  详细解决方案

poj-3694-Network-并查集+tarjan

热度:53   发布时间:2023-12-19 10:54:20.0

做法:

利用tarjan算法求出每一个节点出现时对应的时间戳dfn。

对于每一个桥,恰有一个节点与其对应。

isb[i]标记i之前的边是不是桥。

当连接两点的时候,求出这两个点到根节点的路径上的边,把这些边的isb设置成0;

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define MAXN 500001
using namespace std;
struct list
{int u;int v;int next;
}node[MAXN];
int head[MAXN],vis[MAXN];
int isb[MAXN];
int nums;
int fa[MAXN];
int n,m,cnt;
int dfn[MAXN],low[MAXN],index;
void init()
{nums=0;memset(head,-1,sizeof(head));memset(vis,0,sizeof(vis));for(int i=0;i<=n;i++)fa[i]=i;cnt=0;memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(isb,0,sizeof(isb));index=0;
}
void add(int x,int y)
{node[nums].u=x;node[nums].v=y;node[nums].next=head[x];head[x]=nums++;
}
void tarjan(int u)
{dfn[u]=low[u]=++index;for(int i=head[u];i!=-1;i=node[i].next){if(vis[i])continue;vis[i]=vis[i^1]=1;int v=node[i].v;if(!dfn[v]){fa[v]=u;tarjan(v);low[u]=min(low[u],low[v]);if(low[v]>dfn[u]){cnt++;isb[v]=1;}}else{low[u]=min(low[u],dfn[v]);}}
}
void LCA(int x,int y)
{while(x!=y){if(isb[x])cnt--,isb[x]=0;if(isb[y])cnt--,isb[y]=0;x=fa[x];y=fa[y];}
}
int main()
{int x,y;int cas=0;while(~scanf("%d%d",&n,&m)&&(n||m)){cas++;init();while(m--){scanf("%d%d",&x,&y);add(x,y);add(y,x);}tarjan(1);printf("Case %d:\n",cas);scanf("%d",&m);while(m--){scanf("%d%d",&x,&y);LCA(x,y);cout<<cnt<<endl;}cout<<endl;}}


  相关解决方案