您的位置:首页 > 其它

uva 10972 边—双连通分量

2013-12-14 20:03 375 查看
这个题目的意思是:给出一个无向图 , 先把该图边为有向图 , 如果让这个有向图变成强连通图 , 问最少要增加的边是多少 。

这个题目需要用到两个定理:

1、任意一个边—双连通图被定向后 , 都能成为一个强连通分量 。

2、当一个无向图为边—双连通图时 , 其点的度数至少为2 。

有了这两个定理后,我们只需求出边双连通分量,缩点后,计算度数为1的点的个数为a,度数为
0的点的个数为b,则(a+2*b)/2的上取整就是答案。因为对无向无环图来说,要形成一个存在一条回路至少经过每个点一次的图,则每个点度数至少是
2,并且是一定能通过合理的添边使新图符合要求的。然后还要注意一个特殊情况,假如原图就是边双连通
的,答案应该是0.

在缩点的时候 , “这里用到了并查集” , 如果两个点在原图中是相连的 , 且在并查集中父亲节点不一样 ,
那么这两个点形成的边在原图中一定是桥 。

#include

#include

#include

#include

#include

#include

using namespace std;

const int maxn = 1000 + 5;

int pre[maxn],dfs_clock;

vector G[maxn];

int isbridge[maxn][maxn];

int dfs1(int u,int fa){

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

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

       
int v = G[u][i];

       
if(!pre[v]){

           
int lowv = dfs1(v,u);

           
lowu = min(lowu,lowv);

           
if(lowv > pre[u]){

               
isbridge[u][v] = 1; isbridge[v][u] = 1;

           
}

       
}

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

           
lowu = min(lowu,pre[v]);

       
}

    }

    return
lowu;

}

int fa[maxn],vis[maxn];

int find(int x){return x == fa[x]?x:fa[x] = find(fa[x]);}

void dfs2(int u){

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

       
int v = G[u][i];

       
if(!vis[v] && !isbridge[u][v]){

           
int X = find(u); int Y = find(v);

           
if(X != Y) fa[X] = Y;

           
vis[v] = 1;

           
dfs2(v);

       
}

    }

}

void find_bcc(int n){

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

   
memset(isbridge,0,sizeof(isbridge));

    dfs_clock =
0;

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

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

   
memset(vis,0,sizeof(vis));

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

       
if(!vis[i]) {

           
vis[i] = 1;

           
dfs2(i);

       
}

    }

}

int degree[maxn];

int used[maxn];

int main()

{

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