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

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

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

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

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

用下面这张图同样可以证明为什么边双连通分量中的dfs中更新low值为什么是代码中所说的那样一个过程,因为low[3]是等于1的,而3的dfs顺序,就是dfn[3]=3,到了五号结点的时候,我们发现有回退边(5,3)如果此时我们用3的dfn值来更新5的low值的话就会发现5的low是3,回溯之后发现1,2,3结点low值是1,而4,5结点的low值是3,这样真的正确吗?很遗憾是错误的,为什么呢?我们可以发现,是因为在五号结点访问边(5,3)的时候错过了3号节点的回退边(3,1)在边双连通分量的计算中,回退边是需要包括在内的,这样dfs搜索到这个点之后这个点可以通过多条回退边跳回一个low=dfn结点,这个结点的low值就是他要更新成为的值。故边双连通分量中low的计算可以说是十分简洁但是要区分开和其他tarjan算法的low值计算策略,主要tarjan的这个low值太牛逼了!!!包含了太多的信息orz

代码如下:

 #include<cstring>
#include<vector>
#include<stdio.h>
using namespace std;
const int maxn =;
int n,m,low[maxn],dfn;
vector<int>G[maxn];
void dfs(int u,int fa)//先用dfs处理处每个点的low值,以便相同的low值合并
{//处理low值时不需要处理dfn数组
low[u]=++dfn;
for(int i=;i<G[u].size();i++)
{
int v=G[u][i];
if(v==fa)continue;//保证dfs 树的前向性
if(!low[v])
dfs(v,u);
low[u]=min(low[u],low[v]);
}
}
int tarjan()
{
int degree[maxn];
memset(degree,,sizeof(degree));
for(int i=;i<=n;i++)
{
for(int j=;j<G[i].size();j++)
{
if(low[i]!=low[G[i][j]])
degree[low[i]]++;
}
}
int res=;
for(int i=;i<=n;i++)
{
if(degree[i]==)res++;
}
return res;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
int x,y;
memset(low,,sizeof(low));
for(int i=;i<=n;i++)G[i].clear();
while(m--)
{
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
dfn=;//每次dfs之前设置dfs树的编号从1开始
dfs(,-);
int ans=tarjan();
printf("%d\n",(ans+)/);
}
return ;
}

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

  1. POJ-3352 Road Construction,tarjan缩点求边双连通!

    Road Construction 本来不想做这个题,下午总结的时候发现自己花了一周的时间学连通图却连什么是边双连通不清楚,于是百度了一下相关内容,原来就是一个点到另一个至少有两条不同的路. 题意:给 ...

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

    Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10141   Accepted: 503 ...

  3. POJ3352 Road Construction(边双连通分量)

                                                                                                         ...

  4. [POJ3352]Road Construction

    [POJ3352]Road Construction 试题描述 It's almost summer time, and that means that it's almost summer cons ...

  5. POJ3352 Road Construction (双连通分量)

    Road Construction Time Limit:2000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u Sub ...

  6. POJ3352 Road Construction 双连通分量+缩点

    Road Construction Description It's almost summer time, and that means that it's almost summer constr ...

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

    http://poj.org/problem?id=3352 题意: 给出一个图,求最少要加多少条边,能把该图变成边—双连通. 思路:双连通分量是没有桥的,dfs一遍,计算出每个结点的low值,如果相 ...

  8. poj 3177 Redundant Paths(tarjan边双连通)

    题目链接:http://poj.org/problem?id=3177 题意:求最少加几条边使得没对点都有至少两条路互通. 题解:边双连通顾名思义,可以先求一下连通块显然连通块里的点都是双连通的,然后 ...

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

    题意:有n个点,m条路,问你最少加几条边,让整个图变成边双连通分量. 思路:缩点后变成一颗树,最少加边 = (度为1的点 + 1)/ 2.3177有重边,如果出现重边,用并查集合并两个端点所在的缩点后 ...

随机推荐

  1. Python知识点总结及其介绍链接

    Python 弱引用(不会增加引用计数的引用,可以用来做对象缓存,避免循环引用导致内存无法回收):http://python.jobbole.com/85431/ from future import ...

  2. Introduction Of Gradient Descent

    不是一个机器学习算法 是一种基于搜索的优化方法 作用:最小化一个损失函数 梯度上升法:最大化一个效用函数 import matplotlib.pyplot as plt import numpy as ...

  3. ubuntu16.04问题 · 最初的梦想

    ubuntu 包管理器命令 1 $ sudo synaptic 安装主题 1 $ sudo apt-get install unity-tweak-tool 下载主题 https://www.sysg ...

  4. python通用读取vcf文件的类(可以直接复制粘贴使用)

    前言   处理vcf文件的时候,需要多种切割,正则匹配,如果要自己写其实会比较麻烦,并且每次还得根据vcf文件格式或者需要读取的值不同要修改相应的代码.因此很多人会选择一些python的vcf的库,但 ...

  5. USB小白学习之路(6) IIC EEPROM读取解析

    IIC EEPROM读取解析 1. 编译错误处理(这里可以忽略) 在解压包解压了程序后,直接编译,出现如下错误. *** WARNING L14: INCOMPATIBLE MEMORY MODEL ...

  6. Swift--struct与class的区别(汇编角度底层分析)

    概述 相对Objective-C, Swift使用结构体Struct的比例大大增加了,其中Int, Bool,以及String,Array等底层全部使用Struct来定义!在Swift中结构体不仅可以 ...

  7. 深度学习遥感影像(哨兵2A/B)超分辨率

    这段时间,用到了哨兵影像,遇到了一个问题,就是哨兵影像,它的RGB/NIR波段是10米分辨率的,但是其他波段是20米和60米的,这就需要pansharpening了,所以我们需要设计一种算法来进行解决 ...

  8. JS面试准备二

    1.常用的字符串方法 1. indexOf:查找字符串某一项的初始位置2. slice:截取字符串(包含起始位置,不包含结束位置) 不会根据参数大小,交换参数位置 如果出现-1按倒数第一个数,如果出现 ...

  9. NetAnalyzer笔记 之 十一 打造自己的协议分析语言(1)初衷与语法构想

    回头看看NetAnalyzer开发系文档上次一篇竟然是2016年,老脸一红.不过这几年墨云成功过的讨到一个温柔贤淑的老婆,有了一个幸福的家庭,去年9月又有了一个大胖儿子,想想也就释然了^_^ 其实这几 ...

  10. 逐浪web无障碍与国际化以及全民族语言支持白皮书

    北京时间2019年5月10日,领先的门户网站与WEB内核服务厂商--上海Zoomla!逐浪CMS团队发布其年度重榜产品:逐浪CMS全民族语言与国际版,体验站点:http://demo2.z01.com ...