题目链接: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 字符编码判断

    题记 在获取中文字符的时候,如果出现乱码的情况,我们需要了解当前的字符串的编码形式.使用下面两种方法可以判断字符串的编码形式. 法一: isinstance(s, str) 用来判断是否为一般字符串 ...

  2. React.js/HTML5和iOS双向通信

    最近,我使用WKWebView和React.js进行双向通信,自己写了React.js嵌入到Native中. Native操作Web,通过两种方式传值 第一种,通过JS传值给Native 通过这种方式 ...

  3. myeclipse安装插件svn的步骤

    下载插件地址:http://subclipse.tigris.org/ 方法一:本地安装 1.打开HELP->MyEclipse Configuration或者myeclipse->MyE ...

  4. C:指针习题

    1. 请指出以下程序段中的错误. 程序中的错误有:(1)p=i:类型不匹配.(2)q=*p:q 是指针,*p 是指针 p 指向变量的值.(3)t='b':t 是指针类型. 解释:指针变量是一种存放地址 ...

  5. Flash之后是不是该IE浏览器了

    Flash死亡,Adobe推荐大家拥抱HTML5. 其实Flash本身也是支持手机端的. 一.Flash宣告死亡 Adoebe官方网站发布了公告,2020年12月30日起终止支援Flash.目前Chr ...

  6. jq拖拽插件

    (function ($) { var move = false; //标记控件是否处于被拖动状态 var dragOffsetX = 0; //控件左边界和鼠标X轴的差 var dragOffset ...

  7. Particle Filter Algorithm

    目录 问题提出 算法研究现状 算法原理 问题提出 在现实科研问题中,其中有很多都是非线性的.要想求得问题的解,就需要非线性的算法.所谓非线性滤波,就是基于带有噪声的观测值,估计非线性系统动态变化的状态 ...

  8. Spark ML机器学习库评估指标示例

    本文主要对 Spark ML库下模型评估指标的讲解,以下代码均以Jupyter Notebook进行讲解,Spark版本为2.4.5.模型评估指标位于包org.apache.spark.ml.eval ...

  9. Hibernate和Mybatis的工作原理以及区别

    一.Mybatis的工作流程图 (1).原理详见: MyBatis应用程序根据XML配置文件创建SqlSessionFactory,SqlSessionFactory在根据配置,配置来源于两个地方,一 ...

  10. kafka知识整理

    title: kafka知识整理 date: 2019-06-18 10:59:46 categories: MQ tags: kafka --- 转载自:https://www.cnblogs.co ...