边双联通问题求解(构造边双连通图)POJ3352(Road Construction)

题目链接:传送门

题目大意:给你一副无向图,问至少加多少条边使图成为边双联通图

题目思路:tarjan算法加缩点,缩点后求出度数为1的叶子节点个数,需要加边数为(leaf+1)/2

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <cstring>
 7 #include <stack>
 8 #include <cctype>
 9 #include <queue>
10 #include <string>
11 #include <vector>
12 #include <set>
13 #include <map>
14 #include <climits>
15 #define lson root<<1,l,mid
16 #define rson root<<1|1,mid+1,r
17 #define fi first
18 #define se second
19 #define ping(x,y) ((x-y)*(x-y))
20 #define mst(x,y) memset(x,y,sizeof(x))
21 #define mcp(x,y) memcpy(x,y,sizeof(y))
22 #define Min(x,y) (x<y?x:y)
23 #define Max(x,y) (x>y?x:y)
24 using namespace std;
25 #define gamma 0.5772156649015328606065120
26 #define MOD 1000000007
27 #define inf 0x3f3f3f3f
28 #define N 5005
29 #define maxn 10005
30 typedef long long LL;
31 typedef pair<int,int> PII;
32
33 vector<int>V[1005];
34 int n,m,hcnt,deep;
35 struct Node{
36     int to,next;
37     Node(){}
38     Node(int a,int b):to(a),next(b){}
39 }node[N];
40 int head[N],vis[N],low[N],dfn[N];
41 int d[N];
42
43 inline void add(int x,int y){
44     node[hcnt]=Node(y,head[x]);
45     head[x]=hcnt++;
46 }
47
48 inline void init(){
49     mst(d,0);
50     mst(vis,0); vis[1]=1;
51     mst(head,-1);
52     hcnt=0;
53     deep=1;
54     low[1]=dfn[1]=1;
55 }
56
57 void dfs(int x,int father){
58     for(int i=head[x];~i;i=node[i].next){
59         int e=node[i].to;
60         if(e==father)continue;
61         if(vis[e])low[x]=min(low[x],dfn[e]);
62         else{
63             vis[e]=1;
64             low[e]=dfn[e]=++deep;
65             dfs(e,x);
66             low[x]=min(low[x],low[e]);
67         }
68     }
69 }
70
71 int main(){
72     int i,j,group,Case=0,x,y;
73     while(scanf("%d%d",&n,&m)!=EOF){
74         for(i=0;i<=n;++i)V[i].clear();
75         init();
76         while(m--){
77             scanf("%d%d",&x,&y);
78             add(x,y);
79             add(y,x);
80             V[x].push_back(y);     ///两点之间联通
81             V[y].push_back(x);     ///在缩点之后用于计算度数
82         }
83         dfs(1,-1);    ///tarjan算法
84         int leaf=0;
85         for(i=1;i<=n;++i)
86         if(V[i].size())
87         for(j=0;j<V[i].size();++j){
88             int e=V[i][j];
89             if(low[i]!=low[e])
90                 d[low[i]]++;
91         }
92         for(i=0;i<=deep;++i)
93             if(d[i]==1)++leaf;
94         printf("%d\n",(leaf+1)/2);
95     }
96     return 0;
97 }
时间: 2024-10-12 23:31:02

边双联通问题求解(构造边双连通图)POJ3352(Road Construction)的相关文章

【连通图|边双连通+缩点】POJ-3352 Road Construction

Road Construction Time Limit: 2000MS Memory Limit: 65536K 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 roads on the tropical island paradise of Remo

POJ3352 Road Construction【边双联通分量】【Tarjan】

题目链接: http://poj.org/problem?id=3352 题目大意: 一个热带天堂岛上有N个旅游景点,任意2个旅游景点之间都有路径(并不一定直接相连).为了使游客 往返更便捷,该旅游公司要求增加一些道路.在施工的时候,每次只能选择一条道路施工,在施工完 毕之前,除了该道路意外,其他道路依旧能够通行.因为施工道路禁止通行,这就导致了在施工期间 游客可能无法到达一些经典. 该公司为了保证在施工期间所有的旅游景点都能够向游客开放,该公司决定搭建一些临时桥梁,使得 无论在哪条道路施工,游

POJ3352 Road Construction Tarjan+边双连通

题目链接:http://poj.org/problem?id=3352 题目要求求出无向图中最少需要多少边能够使得该图边双连通. 在图G中,如果任意两个点之间有两条边不重复的路径,称为“边双连通”,去掉任何一条边都是其他边仍然是连通的,也就是说边双连通图中没有割边. 算法设计是:运用tarjan+缩点.对于每一个边双连通分量,我们都可以把它视作一个点,因为low值相同的点处在同一个边双连通分量中,可以简单地思考一下,(u,v)之间有两条可达的路径,dfs一定可以从一条路开始搜索并且从另一条路回去

poj3352 road construction tarjan求双连通分量

填坑--链接:http://poj.org/problem?id=3352 题意:求出图中再加上几条边会全部边双连通. 思路大概就是求出图中所有的双连通分量,然后像$SCC$一样缩点,缩完后每两个双连通分量再连边即可. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn

poj3352 Road Construction &amp; poj3177 Redundant Paths (边双连通分量)题解

题意:有n个点,m条路,问你最少加几条边,让整个图变成边双连通分量. 思路:缩点后变成一颗树,最少加边 = (度为1的点 + 1)/ 2.3177有重边,如果出现重边,用并查集合并两个端点所在的缩点后的点. 代码: /*3352*/ #include<set> #include<map> #include<stack> #include<cmath> #include<queue> #include<vector> #include&

poj-3177(并查集+双联通分量+Tarjan算法)

题目链接:传送门 思路: 题目要将使每一对草场之间都有至少两条相互分离的路径,所以转化为(一个有桥的连通图至少加几条边才能变为双联通图?) 先将桥删除,然后原图变为多个连通块,每一个连通块就是一个边双联通分量,将双联通子图收缩为一个顶点,再把桥边加回来,边连通度为1, 顺便统计度为1的节点的个数,即叶节点的个数即为cnt,所以至少在树上添加(cnt+1)/2条边. #include<iostream> #include<cstdio> #include<cstring>

POJ 3352 Road Construction 使得无向图边变双连通图

点击打开链接 Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8168   Accepted: 4106 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

POJ 3352 边双联通

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

双联通分量复习

1,边双联通(桥) POJ3177Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17989   Accepted: 7470 Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1..F) to another field, Bessie an