您的位置:首页 > 其它

poj 3352

2013-12-14 20:03 197 查看
这是一题求边—双连通的题目 , 题目给出一个无向图 , 问最少还需要多少边 , 才能让这个图变成边—双连通图 。

解法:

1、 先求出所有桥 ,然后再用dfs去遍历图,且不能经过桥, 这样就能把图中的所有边连通分量求出

2、让后再把所有边连通分量缩成一个点 , 用桥去连接这些点 , 最小边 = (a + b*2 + 1)/2 , a
表示新构成的图中度为1的点 , b是表示度为2的点。

缩点的方法:

   
把第一个连通分量中的所有点都用bcc_cnt来标记 , 而下一个连通分量就用bcc_cnt+1 , 来标记 。
这样就区分了所有连通分量 , 只要原图中一条边的两点在标记中的数不一样 , 那么这两个点的度就加1;

这类似于 , 并查集的父亲节点 , 判断是不是同一个连通图。

需要用的定理:

1、所有边—连通分量是没有公共点的 。

2、缩点之后的最小边为(a + b*2 + 1)/2 。

#include

#include

#include

#include

#include

#include

using namespace std;

const int MAXN = 1010 ;

int pre[MAXN] , bccno[MAXN] , iscnt[MAXN];

vectorgrap[MAXN] ;

int n , m , dfs_clock , bcc_cnt ;

int xy[MAXN][MAXN] , p[MAXN];

 

void init()

{

    for(int i =
0 ; i <= n; i++)

   
   
grap[i].clear();

    memset(xy ,0
, sizeof(xy));

}

int dfs1(int u , int fa)

{

    int lowu =
pre[u] = ++dfs_clock;

    for(int i =
0 ; i < grap[u].size() ; i++)

    {

   
    int v =
grap[u][i];

   
   
if(!pre[v])

   
    {

   
   
    int lowv =
dfs1(v , u);

   
   
    if(lowu <
lowv)  lowu = lowv;

   
   
    if(lowv >
pre[u])  xy[u][v] = xy[v][u] = 1;

   
    }

   
    if(pre[v]
< pre[u] && v != fa)

   
   
    if(pre[v]
< lowu)  lowu = pre[v];

    }

    return
lowu;

}

void dfs2(int u)

{

    p[u] =
bcc_cnt;

    iscnt[u] =
1;

    for(int i =
0 ; i < grap[u].size(); i++)

    {

   
    int v =
grap[u][i];

   
    if(!iscnt[v]
&& !xy[u][v])  dfs2(v);

    }

}

void bcc_find()

{

    memset(pre ,
0 , sizeof(pre));

    memset(bccno
, 0 ,sizeof(bccno));

    memset(iscnt
, 0 , sizeof(iscnt));

    dfs_clock =
bcc_cnt = 0;

    int
i  ;

    for(i = 1; i
<= n; i++)

   
   
if(!pre[i])  dfs1(i , -1);

    for(i = 1; i
<= n; i++)

    {

   
   

   
   
if(!iscnt[i]) bcc_cnt++ , dfs2(i);  // 标记每个连通分量 ,
并构图

    }

}

int main()

{

   
while(scanf("%d %d" , &n , &m)  !=
EOF)

    {

   
   
init();

   
    int i , j ,
x , y;

   
    for(i = 0 ;
i < m; i++)

   
    {

   
   
    scanf("%d
%d" , &x , &y);

   
   
   
grap[x].push_back(y);

   
   
   
grap[y].push_back(x);

   
    }

   
   
bcc_find();

   
    memset(iscnt
, 0 , sizeof(iscnt));

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