/*
Network
POJ - 3694
https://vjudge.net/problem/POJ-3694
在无向图中动态添边,求割边个数
先tarjan缩点建树,在LAC删割边,不懂得画个图就明白了
*/
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
#define maxm 400010
#define maxn 100010
struct Edge{
int v,next;
}edge[maxm];
int head[maxn];
int dfn[maxn],low[maxn];
int judge[maxn];
int pre[maxn];
int cnt,total,ans;
int n,m;
void add(int u,int v){
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void init(){
memset(judge,0,sizeof(judge));
memset(head,-1,sizeof head);
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
for(int i=1; i<=n; i++){
pre[i]=i;
}
cnt=total=ans=0;
}
void tarjan(int u,int fa){
dfn[u]=low[u]=++total;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].v;
if(!dfn[v]){
pre[v]=u;
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]){
ans++;
judge[v]=1;
}
}else if(fa!=v){
low[u]=min(low[u],dfn[v]);
}
}
}
void lca(int u,int v){
while(dfn[u]<dfn[v]){
if(judge[v]){
ans--;
judge[v]=0;
}
v=pre[v];
}
while(dfn[u]>dfn[v]){
if(judge[u]){
ans--;
judge[u]=0;
}
u=pre[u];
}
while(u!=v){
if(judge[u]) ans--;
if(judge[v]) ans--;
judge[u]=0;
judge[v]=0;
u=pre[u];
v=pre[v];
}
}
int main(){
int T=0;
while(~scanf("%d %d", &n, &m)&&(n+m)){
init();
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]) tarjan(i,0);
int t;
printf("Case %d:\n",++T);
scanf("%d", &t);
while(t--){
scanf("%d %d", &u, &v);
lca(u,v);
printf("%d\n", ans);
}
printf("\n");
}
return 0;
}
Network(tarjan缩点建树,在LAC删割边)
猜你喜欢
转载自blog.csdn.net/weixin_44410512/article/details/104249846
今日推荐
周排行