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()
{
这个题目需要用到两个定理:
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()
{
相关文章推荐
- 强连通分量scc
- uva 10765(无向双连通量)
- FZU 2103 组合概率
- 我的博客今天0岁51天了,我领取了…
- poj 1325
- uva 11865 stream my contest
- uva 11865 stream my contest
- 二分图的最佳完美匹配(和一些变形…
- 有向图最小生成树——最小树形图(朱…
- 每个点与点之间的瓶颈路
- LA 5713 Qin&nbsp…
- uva 11354 Bond
- 最小生成树的一些性质和理解
- poj 2485 简单的最小生…
- 我的博客今天0岁42天了,我领取了…
- LA 4080 Warfare A…
- hdu 2433 最短路树
- 【快速】排序, T(n) = O(nlgn),O(n^2) S(n) = O(lgn) --- 不稳定
- (C# 基础) 类访问修饰符
- LA 3713 Astronauts