POJ 3694
题意:一个网络管理员管理一个网络,网络中的电脑直接或间接的相连接,管理员有Q次操作,每次向网络中建立一条新边,向管理员报告桥的个数
思路:先将网络中的桥求出来,在求的过程中进行并查集缩点,在询问的时候,进行最朴素的LCA查找最近公共祖先,在求的过程中判断节点与父节点是不是在同一个集合中,如果不在同一个集合,说明是桥,则这个桥将不存在,将两个集合合并。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 110000;
vector<int> g[maxn];
int dfn[maxn],low[maxn];
int pre[maxn],fa[maxn];
int num;
int n,m,q;
int d_cnt;
int f(int x)
{
if(x!=pre[x]) pre[x]=f(pre[x]);
return pre[x];
}
void hb(int x,int y)
{
int fx = f(x),fy = f(y);
if(fx!=fy) pre[fx]=fy;
}
void dfs(int fat,int u)
{
dfn[u]=low[u]= ++d_cnt;
fa[u]=fat;
for(int i=0;i<g[u].size();++i)
{
int v=g[u][i];
if(v==fat) continue;
if(!dfn[v])
{
dfs(u,v);
low[u] = min(low[u],low[v]);
if(low[v]<=dfn[u]) hb(v,u);
else num++;
}
else low[u]=min(low[u],dfn[v]);
}
}
void tarjan()
{
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
d_cnt=num=0;
for(int i=1;i<=n;++i) if(!dfn[i]) dfs(i,i);
}
void judge(int u)
{
int x=f(u);
int y=f(fa[u]);
if(x!=y)
{
num--;
pre[x]=y;
}
}
void lca(int u,int v)
{
while(dfn[u]>dfn[v])
{
judge(u);u=fa[u];
}
while(dfn[v]>dfn[u])
{
judge(v);v=fa[v];
}
while(u!=v)
{
judge(u); judge(v);
u = fa[u]; v = fa[v];
}
}
int main()
{
int kiss=1;
while(scanf("%d %d",&n,&m)!=EOF)
{
if(n==0&&m==0) break;
int u,v;
for(int i=1;i<=n;++i) g[i].clear();
for(int i=1;i<=n;++i) pre[i]=i;
for(int i=0;i<m;i++)
{
scanf("%d %d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
tarjan();
scanf("%d",&q);
printf("Case %d:\n",kiss++);
while(q--)
{
scanf("%d %d",&u,&v);
if(f(u)!=f(v))
{
lca(u,v);
}
printf("%d\n",num);
}
printf("\n");
}
return 0;
}
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <string.h>
using namespace std;
const int maxn=5005;
bool map[maxn][maxn];
int low[maxn],dfn[maxn];
int d_cnt;
int n,m;
int in[maxn];
void dfs(int u,int pre)
{
low[u]=dfn[u]= ++d_cnt;
for(int i=1;i<=n;++i)
{
if(map[u][i]==0) continue;
if(!dfn[i])
{
dfs(i,u);
low[u]=min(low[i],low[u]);
}
else if(pre!=i)
{
low[u]=min(low[u],dfn[i]);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(map,0,sizeof(map));
int u,v;
for(int i=1;i<=m;++i)
{
scanf("%d%d",&u,&v);
map[u][v]=1; map[v][u]=1;
}
memset(in,0,sizeof(in));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
d_cnt=0;
for(int i=1;i<=n;++i) if(!dfn[i]) dfs(i,i);
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
if(!map[i][j]) continue;
if(i==j) continue;
if(low[i]!=low[j])
{
in[low[j]]++;
}
}
}
int temp=0;
for(int i=1;i<=n;++i)
{
if(in[i]==1) temp++;
}
printf("%d\n",(temp+1)/2);
return 0;
}