POJ3352 Road Construction Tarjan+边双连通

题目链接:http://poj.org/problem?id=3352

题目要求求出无向图中最少需要多少边能够使得该图边双连通。

在图G中,如果任意两个点之间有两条边不重复的路径,称为“边双连通”,去掉任何一条边都是其他边仍然是连通的,也就是说边双连通图中没有割边。

算法设计是:运用tarjan+缩点。对于每一个边双连通分量,我们都可以把它视作一个点,因为low值相同的点处在同一个边双连通分量中,可以简单地思考一下,(u,v)之间有两条可达的路径,dfs一定可以从一条路开始搜索并且从另一条路回去。而边双连通分量最初开始搜索的一个点的编号就是这个边双连通分量的low值,因为假设这个点的low值更加靠前的话,他与之前的结点一定是边双连通的关系,有一条边搜索到这个点,这个点在之后还有一条不重合的路径能到达先前那个结点,与边双连通分量的最大性产生矛盾,其实我们也可以把那个点收纳进这个边连通分量,把它作为该连通分量第一个进入dfs树的结点。故有边双连通分量中的点low值相同。

最终将这些点变成一个新的点图,这个点图中最大的边双连通分量就是一个点,所以我们只要看在这张图中需要加多少条边可以使得它边双连通就行。可以证明使得缩点图边双连通加上的边数是 (1+度数为1的点的数量)/2。由于这些缩点的low值都是不同的,所以我们可以用low值作为degree(点的度数)的索引。计算度数的时候时候扫描所有的点,只要跟一个low值不同的点有边,那么该low值(缩点)一定有一个外界的度(可看成入度),最后统计最终的只有一个度的连通分量数量即可。

代码如下:

 1 #include<cstring>
 2 #include<vector>
 3 #include<stdio.h>
 4 using namespace std;
 5 const int maxn =1005;
 6 int n,m,low[maxn],dfn;
 7 vector<int>G[maxn];
 8 void dfs(int u,int fa)//先用dfs处理处每个点的low值,以便相同的low值合并
 9 {//处理low值时不需要处理dfn数组
10     low[u]=++dfn;
11     for(int i=0;i<G[u].size();i++)
12     {
13         int v=G[u][i];
14         if(v==fa)continue;//保证dfs 树的前向性
15         if(!low[v])
16             dfs(v,u);
17             low[u]=min(low[u],low[v]);
18      }
19 }
20 int tarjan()
21 {
22     int degree[maxn];
23     memset(degree,0,sizeof(degree));
24     for(int i=1;i<=n;i++)
25     {
26         for(int j=0;j<G[i].size();j++)
27         {
28             if(low[i]!=low[G[i][j]])
29                 degree[low[i]]++;
30         }
31     }
32     int res=0;
33     for(int i=1;i<=n;i++)
34     {
35         if(degree[i]==1)res++;
36     }
37     return res;
38 }
39 int main()
40 {
41     while(~scanf("%d%d",&n,&m))
42     {
43         int x,y;
44         memset(low,0,sizeof(low));
45         for(int i=0;i<=n;i++)G[i].clear();
46         while(m--)
47         {
48             scanf("%d%d",&x,&y);
49             G[x].push_back(y);
50             G[y].push_back(x);
51         }
52         dfn=0;//每次dfs之前设置dfs树的编号从1开始
53         dfs(1,-1);
54         int ans=tarjan();
55         printf("%d\n",(ans+1)/2);
56     }
57     return 0;
58  } 

原文地址:https://www.cnblogs.com/randy-lo/p/12585226.html

时间: 2024-11-07 16:59:52

POJ3352 Road Construction Tarjan+边双连通的相关文章

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【边双联通分量】【Tarjan】

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

poj 3352 Road Construction【边双连通求最少加多少条边使图双连通&amp;&amp;缩点】

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10141   Accepted: 5031 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 r

【连通图|边双连通+缩点】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

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

http://poj.org/problem?id=3352 题意: 给出一个图,求最少要加多少条边,能把该图变成边—双连通. 思路:双连通分量是没有桥的,dfs一遍,计算出每个结点的low值,如果相等,说明属于同一个双连通分量. 接下来把连通分量缩点,然后把这些点连边. 对于一棵无向树,我们要使得其变成边双连通图,需要添加的边数 == (树中度数为1的点的个数+1)/2. 1 #include<iostream> 2 #include<algorithm> 3 #include&

poj 3177 Redundant Paths(tarjan边双连通)

题目链接:http://poj.org/problem?id=3177 题意:求最少加几条边使得没对点都有至少两条路互通. 题解:边双连通顾名思义,可以先求一下连通块显然连通块里的点都是双连通的,然后就是各个连通块之间的问题. 也就是说只要求一下桥,然后某个连通块桥的个数位1的总数,结果就是(ans+1)/2.为什么是这个结果自行画图 理解一下,挺好理解的. #include <iostream> #include <cstring> #include <cstdio>

【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

边双联通问题求解(构造边双连通图)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

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&