您的位置:首页 > 其它

poj3352 Road Construction 边双连通分量tarjan算法

2017-10-03 21:21 369 查看
http://poj.org/problem?id=3352

题意:有n个城市m条道路,一开始任何两个城市相互可达。现在需要某条修路,修路时该道路不可通行。然后需要搭建临时的桥,使得任何两个城市仍是相互可达的。求最少需要搭建的桥的数量。

题解:这是一个无向图,去掉一条边就不连通。那么这条边就是桥。现在要搭建临时的桥,搭建完后与原图一起,这个有向图就是边双连通的(边连通度大于1)。现在就是求加上几条边使得这个无向图是边双连通的。

首先tarjan求出边双连通分量,对边双连通分量进行缩点,那么就形成一棵树。

然后就是对于一棵树,如何加边使得它边双连通,有一个结论:加边数=(叶子节点数+1)/2。即加边后无度数为1的点。

代码:

#include<set>
#include<map>
#include<queue>
#include<vector>
#include<string>
#include<bitset>

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>

#include<iomanip>
#include<iostream>

#define debug cout<<"aaa"<<endl
#define d(a) cout<<a<<endl
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define MIN_INT (-2147483647-1)
#define MAX_INT 2147483647
#define MAX_LL 9223372036854775807i64
#define MIN_LL (-9223372036854775807i64-1)
using namespace std;

const int N = 1000 + 5;
const int mod = 1000000000 + 7;
const double eps = 1e-8;
int head
,len;
int dfn
,low
,dfs_num;//dfn表示遍历深度,low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号
int deg
,ans;

struct EdgeNode{
int to,next;
}edge
;

void add(int i,int j){
edge[len].to=j;
edge[len].next=head[i];
head[i]=len++;
}

void init(){
mem(deg,0),mem(dfn,0),mem(low,0),mem(head,-1),ans=len=dfs_num=0;
}

void tarjan(int x,int from){
dfn[x]=low[x]=++dfs_num;
for(int i=head[x];i!=-1;i=edge[i].next){
int temp=edge[i].to;
if(temp==from) continue;
if(!dfn[temp]){
tarjan(temp,x);
low[x]=min(low[x],low[temp]);
}
else{
low[x]=min(dfn[temp],low[x]);
}
}
}

void solve(int n){
for(int i=1;i<=n;i++){
if(!dfn[i]){
tarjan(i,-1);
}
}
for(int i=1;i<=n;i++){
for(int k=head[i];k!=-1;k=edge[k].next){
int temp=edge[k].to;
//不属于同一个边连通分量
if(low[i]!=low[temp]){
deg[low[i]]++;
}
}
}
//这里的i表示low[]
for(int i=1;i<=n;i++){
if(deg[i]==1){
ans++;
}
}
ans=(ans+1)/2;
}

int main(){
int n,m,u,v;
char a;
while(~scanf("%d%d",&n,&m)){
init();
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
solve(n);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: