您的位置:首页 > 其它

poj 3352 Road Construction(边双连通)

2012-11-13 16:50 357 查看
题意:一个国家有N个城市,有M条路连接这N个城市,通过这些路任意两个城市都可以互达,现在为了游客的安全,决定重新修葺一下这些路,但是为了能方便游客,需要新修一些路,使得任意两城市间都有两条路。

思路:先求强连通分支,然后缩点,这样就形成了一个树,找到叶子节点ans,只要修(ans+1)/2条路就可以达到目的了。

代码:

View Code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <math.h>
#include <stack>
#define  N 1005
using namespace std ;

struct node
{
int e , next ;
}p[2*N];

int dfn
, low
, out
, head
;
int n , m , cnt , id , num , ans ;

//求强连通分支
void dfs( int x , int fa )
{
dfn[x] = low[x] = ++id ;

for ( int i = head[x] ; i != -1 ; i = p[i].next )
{
int v = p[i].e ;
if ( v != fa && !dfn[v] )
{
dfs( v , x ) ;
low[x] = min( low[x] , low[v]);
if ( low[v] > dfn[x] )
{
cnt++;
}
}
else if ( v != fa && low[x] > dfn[v] )
low[x] = dfn[v] ;
}
}

int main()
{
int i , j , x , y ;

while ( scanf ( "%d%d" , &n , &m ) != EOF )
{
//建图
memset( head , -1 , sizeof( head )) ;
num = 0 ;
for ( i = 1 ; i <= m ; i++ )
{
scanf ( "%d%d" , &x , &y ) ;
p[num].e = y ;
p[num].next = head[x] ;
head[x] = num++ ;

p[num].e = x ;
p[num].next = head[y] ;
head[y] = num++ ;
}

//初始化
cnt = id = ans = 0 ;
memset( out , 0 , sizeof ( out )) ;

//缩点
dfs ( 1 , -1 ) ;

//找叶子节点,度为1的为叶子节点
for ( i = 1 ; i <= n ; i++ )
{
for ( j = head[i] ; j != -1 ; j = p[j].next )
{
int v = p[j].e ;
if ( low[i] != low[v] )
{
out[low[i]]++ ;
}
}
}
for ( i = 1 ; i <= n ; i++)
if ( out[i] == 1 )
ans++ ;

printf ( "%d\n" , ( ans + 1 ) / 2 ) ;
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: