您的位置:首页 > 其它

给定一个连通图 q个询问 每次加一条边 每次求出有多少个桥 poj 3694

2018-03-20 18:10 295 查看
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 101000;
vector<int> mp[maxn];
int dfn[maxn],low[maxn],pre[maxn],p[maxn],cnt,ans;
int find(int u){
return u == pre[u]?u:(pre[u] = find(pre[u]));
}
int unio(int u,int v){
int t1 = find(u);
int t2 = find(v);
if(t1 == t2) return 0;
pre[t1] = t2;
return 1;
}
void Tarjan(int u,int fa){
dfn[u] = low[u] = ++cnt;
for( int i = 0; i < mp[u].size(); i++){
int v = mp[u][i];
if(v == fa) continue;
if(!dfn[v]){
p[v] = u;
Tarjan(v,u);
low[u] = min(low[u],low[v]);
if(low[v] > dfn[u]){
ans++;
}else unio(u,v);
}else{
low[u] = min(low[u],dfn[v]);
}
}
}
void lca(int u,int v){
if(dfn[v] < dfn[u]) swap(v,u);
while(dfn[v] > dfn[u]){
if(unio(v,p[v])) ans--;
v = p[v];
}
while(v != u){
if(unio(u,p[u])) ans--;
u = p[u];
}
}
int main(){
int n,m,q,u,v,t=1;
while(scanf("%d%d",&n,&m) == 2 && m+n){
ans = cnt = 0;
for( int i = 0; i <= n; i++){
pre[i] = i;
}
while(m--){
scanf("%d%d",&u,&v);
mp[u].push_back(v);
mp[v].push_back(u);
}
p[1] = 1;
Tarjan(1,1);
scanf("%d",&q);
printf("Case %d:\n",t++);
while(q--){
scanf("%d%d",&u,&v);
lca(u,v);
printf("%d\n",ans);
}
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐