您的位置:首页 > 其它

POJ 3694 Network(双连通分量)

2014-02-10 20:42 645 查看
http://poj.org/problem?id=3694

题意 : N个点,M条边,构成一个连通图,将图中加入特定的一些边,每加一条边就输出加入这条边后图中剩的桥的个数。

思路 :双连通分量,用LCA

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <stdio.h>
#include <string.h>

using namespace std;

const int maxn = 100005 ;
const int maxm = 555555 ;
const int INF = 1000000000 ;

struct Edge
{
int v, next;
}map[maxm];

int low[maxn],dfn[maxn],index,vis[maxn] ;
int e,n,m,a,b,head[maxn] ;
int cnt,bridge[maxn],father[maxn] ;

void Init()
{
e = 0 ; index = 0 ; cnt = 0 ;
memset(vis,0,sizeof(vis)) ;
memset(bridge,0,sizeof(bridge)) ;
memset(dfn,0,sizeof(dfn)) ;
memset(head,-1,sizeof(head)) ;
for(int i = 1 ; i <= n ; i++)
father[i] = i ;
}

void addedge(int v,int w)
{
map[e].v = w ;
map[e].next = head[v] ;
head[v] = e++ ;
}

void tarjan(int u)
{
vis[u] = 1 ;
dfn[u] = low[u] = ++index ;
for(int i = head[u] ; i+1 ; i = map[i].next)
{
int v = map[i].v ;
if(!vis[v])
{
father[v] = u ;
tarjan(v) ;
low[u] = min(low[u],low[v]) ;
if(low[v] > dfn[u])
{
cnt++ ;
bridge[v] = 1 ;
}
}
else if(vis[v] == 1 && v != father[u])
low[u] = min(low[u],dfn[v]) ;
}
vis[u] = 2 ;
}

void lca(int u,int v)
{
while(dfn[u] > dfn[v])
{
if(bridge[u]) cnt--,bridge[u] = 0 ;
u = father[u] ;
}
while(dfn[v] > dfn[u])
{
if(bridge[v]) cnt--,bridge[v] = 0 ;
v = father[v] ;
}
while(u != v)
{
if(bridge[u]) cnt--,bridge[u] = 0 ;
if(bridge[v]) cnt--,bridge[v] = 0 ;
u = father[u] ;
v = father[v] ;
}
}
int main()
{

int kase = 0 ;
while(scanf("%d %d",&n,&m)!=EOF)
{
if(n == 0 && m == 0) break ;

Init() ;
while(m--)
{
scanf("%d %d",&a,&b) ;
addedge(a,b) ;
addedge(b,a) ;
}
tarjan(1) ;
int k ;
scanf("%d",&k) ;
printf("Case %d:\n",++kase) ;
while(k--)
{
scanf("%d %d",&a,&b) ;
lca(a,b) ;
printf("%d\n",cnt) ;
}
printf("\n") ;
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: