Road Construction POJ - 3352 (边双连通分量)

Road Construction

POJ - 3352

题意:一个无向图(无重边),问至少还要加多少边使得去掉任意一条边后任意两点仍可互达。

无向图的边双连通分量(无重边)

先用一次dfs标记出割边,然后dfs标记出各联通分量

再根据割边,缩点重新建图,生成一颗树

则答案就是(叶子树+1)/2.

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 using namespace std;
 6 const int maxv=1010;
 7 int n,m;
 8 struct Edge{
 9     int v,nex;
10     bool iscut;
11 }e[maxv<<1];
12 int head[maxv];
13 int cnt=0;
14 void init(){
15     memset(head,-1,sizeof(head));
16     cnt=0;
17 }
18 void add(int u,int v){
19     e[cnt].iscut=0;
20     e[cnt].v=v;
21     e[cnt].nex=head[u];
22     head[u]=cnt++;
23 }
24
25 int pre[maxv],d[maxv],bccno[maxv],dfsk,bcc_cnt;
26 bool vis[maxv];
27
28 int dfs(int u,int f){
29     int lowu=pre[u]=++dfsk;
30     for(int i=head[u];i!=-1;i=e[i].nex){
31         int v=e[i].v;
32         if(!pre[v]){
33             int lowv=dfs(v,u);
34             lowu=min(lowv,lowu);
35             if(lowv>pre[u]) e[i].iscut=e[i^1].iscut=true;
36         }
37         else if(pre[v]<pre[u]&&v!=f) lowu=min(lowu,pre[v]);  //反向边
38     }
39     return lowu;
40 }
41 void dfs1(int u){
42     vis[u]=1;
43     bccno[u]=bcc_cnt;
44     for(int i=head[u];i!=-1;i=e[i].nex){
45         if(e[i].iscut) continue;
46         if(!vis[e[i].v]) dfs1(e[i].v);
47     }
48 }
49 void find_bcc(int n){
50     memset(pre,0,sizeof(pre));
51     memset(bccno,0,sizeof(bccno));
52     memset(vis,0,sizeof(vis));
53     dfsk=bcc_cnt=0;
54     for(int i=0;i<n;i++) if(!pre[i]) dfs(i,-1);
55     for(int i=0;i<n;i++)
56         if(!vis[i]) bcc_cnt++,dfs1(i);
57 }
58
59 int main(){
60     while(scanf("%d%d",&n,&m)!=EOF){
61         init();
62         int u,v;
63         for(int i=0;i<m;i++){
64             scanf("%d%d",&u,&v);
65             u--;v--;
66             add(u,v);
67             add(v,u);
68         }
69         find_bcc(n);
70         memset(d,0,sizeof(d));
71         for(int i=0;i<n;i++){
72             for(int j=head[i];j!=-1;j=e[j].nex){
73                 int v=e[j].v;
74                 if(e[j].iscut) d[bccno[v]]++;
75             }
76         }
77         int leaf=0;
78         for(int i=1;i<=bcc_cnt;i++)
79             if(d[i]==1) leaf++;
80         printf("%d\n",(leaf+1)/2);
81     }
82     return 0;
83 }

时间: 2024-11-07 06:30:54

Road Construction POJ - 3352 (边双连通分量)的相关文章

双连通分量 Road Construction POJ - 3352

@[双连通分量] 题意: 有一个 n 个点 m 条边的无向图,问至少添加几条边,能让该图任意缺少一条边后还能相互连通. 双连通分量定义: 在无向连通图中,如果删除该图的任何一个结点都不能改变该图的连通性,则该图为双连通的无向图.一个连通的无向图是双连通的,当且仅当它没有关节点(这里面节点可换成边:分点双连通分量 ,分边双连通分量). 思路: 首先缩点成树: 与强连通分量缩点有所不同:记录父节点 ,不返回父节点 (意味着一条边只能从任意方向走一次) :如果已经走过 ,直接可更新low值(目前理解:

【POJ3352】Road Construction tarjan求边-双连通分量,裸题模板题

转载请注明出处:http://blog.csdn.net/vmurder/article/details/42671851 其实我就是觉得原创的访问量比未授权盗版多有点不爽233... 裸题只给模板. tarjan可以实现. 太水不发题解. 代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 1010 #define M 202

POJ 3352 Road Construction POJ 3177 Redundant Paths(边双连通图 Tarjan+缩点)

POJ 3352 Road Construction POJ 3177 Redundant Paths(边双连通图 Tarjan+缩点) ACM 题目地址: POJ 3352 Road Construction POJ 3177 Redundant Paths 题意: 问要添加几条边才能使所给无向图图变成边双连通图. 分析: 边连通度:使无向图G不连通的最少删边数量为其边连通度. 边双连通图:边连通度大于1的无向图. 首先缩点,让图变成一个DAG. 现在问题转化为:在树中至少添加多少条边能使图变

poj 3352Road Construction(无向双连通分量的分解)

1 /* 2 题意:给定一个连通的无向图G,至少要添加几条边,才能使其变为强连通图(指的是边强联通). 3 思路:利用tarjan算法找出所有的双联通分量!然后根据low[]值的不同将双联通分量 4 进行缩点,最后图形会变成一棵树!也就是添加至少多少条边使一棵树变成强联通图! 5 6 知识点:若要使得任意一棵树,在增加若干条边后,变成一个双连通图,那么 7 至少增加的边数 =( 这棵树总度数为1的结点数 + 1 )/ 2 8 9 */ 10 #include<iostream> 11 #inc

Poj 3352 Road Construction &amp; Poj 3177 Redundant Paths(边双连通分量+缩点)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9465   Accepted: 4699 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the ro

poj 3177 3352 边双连通分量

题目链接:http://poj.org/problem?id=3177 题意:至少加多少边才能构成边双连通图. 思路:求边双连通分量,对于每一个边双连通分量都看做一个点,也就是进行缩点,然后就构造出一个树,然后在这个树上加多少个树边,能够变成一个双连通图. 加的数量就是( 这棵树总度数为1的结点数 + 1 )/ 2 #include <iostream> #include <cstdio> #include <cstring> #include <algorith

POJ 3352 Road Construction&amp;&amp; POJ 3177 Redundant Paths 双联通分量

大意:给定n点,和m条边的关系图中的一些边随时可能施工导致不能够通过,所以至少加多少条边才能够使得途中任意两条边联通? 思路:很明显只要图中的任意两点都是两条边来链接即可.那么我们可以先缩点构建新图,然后统计出度为1的点的个数ans,那么需要加的边数就是(ans+1)/2条; (PS;因为建图是双向的图所以,在Tarjan缩点的时候就需要遇到临边便越过,并且判断是不是同一个联通分支用num比较!) #include<map> #include<queue> #include<

POJ 3352 边双联通

点击打开链接 题意:题目很长不说了,就是求加几条边后,任意删除一条边后,图还是联通的 思路:边双联通分量的定义就是删除一条边后图仍联通,这里推荐这篇点这里写的很详细,而这题就是推荐文章中的构造双联通图中桥的方法,那么我们直接引用,证明看那篇文章把,对于一个联通图,我们求出所有桥,求桥的方法与割点类似,都是求出low和dfs数组完成,我的代码中是L和E数组,将桥删除后的图肯定是多个联通块,而每个块肯定是一个双联通子图,这由桥的定义可以看出来,然后将每一块缩成一个点,连起来后找到度为1的点的个数+1

POJ 3694 边双连通分量+LCA

Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6837   Accepted: 2435 Description A network administrator manages a large network. The network consists of N computers and M links between pairs of computers. Any pair of computers