版权声明:本人蒟蒻,如有大佬转发,感激不尽,带上我的博客链接即可。 https://blog.csdn.net/qq_36300700/article/details/81867558
借鉴了一位大佬的博客:https://blog.csdn.net/sdj222555/article/details/7211644
题意:一个网络管理员管理一个网络,网络中的电脑直接或间接的相连接,管理员有Q次操作,每次向网络中建立一条新边,向管理员报告桥的个数。(输入保证强连通)
分析:这题的大概思路就是,先求割边并标记,然后缩点,形成一棵树,然后把这颗树上各个结点的父结点用dfs求出来,再然后就是LCA了,因为加入某条边后,树内会形成一个圈,这个圈上所有的边将不再是桥,可以发现跟LCA的关联。
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#include <map>
#include <stack>
#include <queue>
using namespace std;
const int maxn =100000+5;
int N,M,Q;
int low[maxn],pre[maxn],dfn[maxn],fa[maxn],iscut[maxn],dfs_clock,cnt,k=1;
vector<int>G[maxn];
void init()
{
for(int i=1; i<=N; i++)
{
G[i].clear();
fa[i]=i;
}
memset(iscut,0,sizeof(iscut));
memset(pre,0,sizeof(pre));
memset(dfn,0,sizeof(dfn));
cnt=dfs_clock=0;
}
int dfs(int u)
{
dfn[u]=dfn[fa[u]]+1;
int lowu = pre[u] = ++dfs_clock;
for(int i=0; i<G[u].size(); i++)
{
int v = G[u][i];
if(!pre[v])
{
fa[v]=u;
int lowv = dfs(v);
lowu = min(lowu,lowv);
if(lowv>pre[u])
{
iscut[v]=1;
cnt++;
}
}
else if(pre[v]<pre[u]&&v!=fa[u])
{
lowu = min(lowu,pre[v]);
}
}
low[u]=lowu;
return lowu;
}
void ask()
{
printf("Case %d:\n",k++);
scanf("%d",&Q);
while(Q--)
{
int A,B;
scanf("%d %d",&A,&B);
while(dfn[A]>dfn[B])
{
if(iscut[A])
{
iscut[A]=0;
cnt--;
}
A=fa[A];
}
while(dfn[B]>dfn[A])
{
if(iscut[B])
{
iscut[B]=0;
cnt--;
}
B=fa[B];
}
while(A!=B)
{
if(iscut[A])
{
iscut[A]=0;
cnt--;
}
if(iscut[B])
{
iscut[B]=0;
cnt--;
}
A=fa[A],B=fa[B];
}
printf("%d\n",cnt);
}
printf("\n");
}
int main()
{
while(scanf("%d %d",&N,&M)&&(N+M))
{
init();
int u,v;
for(int i=1; i<=M; i++)
{
scanf("%d %d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1);
ask();
}
return 0;
}