DFS应用——找出无向图的割点
【0】README
0.1) 本文总结于 数据结构与算法分析, 源代码均为原创, 旨在 理解 "DFS应用于找割点" 的idea 并用源代码加以实现;
0.2) 必须要事先 做个specification的是:对于给定图的除开起始vertex的那些 vertexes,都可以通过我们的 rules(见下文)找出割点,即对于根(start),我们需要做个special 的test,参见main函数中最后的源码;
【1】 无向图割点相关
1.1)割点定义(articulate point): 如果一个图不是双连通的, 那么将其删除后图将不再连通的那些顶点叫做割点;
1.2)双连通性定义: 如果一个连通的无向图中的任一顶点删除之后, 剩下的图仍然是连通的, 那么这样的无向连通图就是 双连通的;
1.3)看个荔枝: 如果节点是 路由器或者交换机 的话, 边是网络链路, 那么若有一台 路由器或者交换机 出故障而不能运行, 则网络并不会受到影响的;
【2】深度优先搜索提供一种找出连通图中的所有割点的线性时间算法
2.1)首先, 从图中任一顶点开始, 执行深度优先搜索并在顶点被访问时给它们编号, 对于每一个顶点,我们称其为先序编号 Num(v) (注:在源代码中,vertexIndex 表示Num的含义,下文不再累述);
2.2)然后, 对于深度优先搜索生成树上的每一个顶点v, 计算编号最低的顶点, 我们称之为 Low(v),该点从v 开始, 通过树的零条或多条边且可能还有一条背向边而达到 (注:在源代码中,vertexLow 表示Low的含义,下文不再累述);
Attention)右上图中的深度优先搜索树首先指出先序编号,然后指出上述法则下可达到的最低编号顶点;
2.3)从A、B、C开始的可达到最低编号顶点为1(A), 因为它们都能够通过树的边到D, 然后再由一条背向边回到A;
2.4)我们可以通过对该深度优先生成树执行一次后序遍历有效地算出 Low, 根据low的定义,可知Low(v)是:
- (1) Num(v) +
- (2) 所有背向边(v, w)中的最低Num(w) +
- (3) 树的所有边(v, w)中的最低Low(w), 以上三者中 的最小者;
- 对以上规则的分析: 第一个条件是不选取边; 第二种方法是不选取树的边 而是选取一条背向边;第三种方法则是选择树的某些边以及可能还有一条背向边;
Attention)
- A1)由于我们需要对v 的所有儿子计算出 Low 值后才能计算Low(v) , 因此这是一个后序遍历;
- A2)对于任一条边(v, w), 我们只要检查Num(v)和 Num(w)就可以知道它是树的一条边还是一条背向边(因为如果是深度优先树的边, Num(v) < Num(w), 因为v比w先被访问到, 而如果是背向边,Num(v) >Num(w)的 );
- A3)因此, Low(v) 容易计算: 我们仅仅需要扫描v 的邻接表,应用适当 的法则,并记住最小值。 所有的计算花费 O(|E| + |V|);
【3】剩下要做的就是利用 这些信息找出所有的割点。
3.1)对于根(见本文README部分):根是割点当且仅当它有多于一个的儿子(根至少要有两个儿子),因为如果它有两个儿子, 那么删除根则使得节点不连通而分布在不同的子树上;如果根只有一个儿子, 那么除去该根只不过是断离该根。
3.2)对于任何其他顶点v: 它是割点当且仅当它有某个儿子w 使得Low(w)>= Num(v); (注意, 这个条件在根处总是满足的; 因此,需要进行特别的测试)(干货)
【4】source code + printing results
4.1)download source code: https://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/chapter9/p242_dfs_findArticulation
4.2)source code at a glance:(for complete code , please click the given link above)
- 4.2.1) 找割点的函数
// "find the articulation point from the given graph"
void findArticulate(Vertex vertex, int depth)
{
int i;
AdjTable temp;
Vertex adjVertex;
visited[vertex] = 1; // update visited status of vertex
vertexIndex[vertex] = counter++; // evaluating vertex index with counter
vertexLow[vertex] = vertexIndex[vertex]; // the 1st rule: evaluating vertex low with counter
temp = adj[vertex];
while(temp->next)
{
adjVertex = temp->next->vertex;
if(visited[adjVertex]) // judge whether the adjVertes was visited before
{
if(vertexIndex[vertex] > vertexIndex[adjVertex] && parent[vertex] != adjVertex)
{
parent[adjVertex] = vertex; // building back side, attention of condition of building back side above
//ex vertex= 3, adjVertex = 0
// just for printing effect
for(i = 0; i < depth; i++)
printf(" ");
printf("vertex[%c]->vertex[%c] (backside) \n", flag[vertex], flag[adjVertex]);
// only if there's a backside, we apply the 2rd rule into the graph
vertexLow[vertex] = minimum(vertexLow[vertex], vertexIndex[adjVertex]); // the 2rd rule: find lowest vertexIndex[w] among all edges(v, w)
}
}
// if(!visited[adjVertex])
// there's the case no backside, and if condition sentences refers to case of backside
else
{
parent[adjVertex] = vertex;
// just for printing effect
for(i = 0; i < depth; i++)
printf(" ");
printf("vertex[%c]->vertex[%c] (building edge)\n", flag[vertex], flag[adjVertex]);
findArticulate(adjVertex, depth+1);
if(vertex != start) // judge whether the vertex is the start (root) or not
if(vertexLow[adjVertex] >= vertexIndex[vertex])
printf("\n\t vertex[%c] proves to be an articulation point !", flag[vertex]);
vertexLow[vertex] = minimum(vertexLow[vertex], vertexLow[adjVertex]); // the 3rd rule: find lowest verdexLow[w] among all edges(v, w)
}
temp = temp->next;
}
}
- 4.2.2) 判断start顶点是否是割点的函数
int isStartArticulation()
{
int i;
AdjTable temp;
Vertex adjVertex;
temp = adj[start];
while(temp->next)
{
adjVertex = temp->next->vertex;
if(adjVertex == start)
{
temp = temp->next;
continue;
}
dfs(adjVertex, 1);
for(i=0; i<size; i++)
if(visited[i] != 1) // "refers that the start vertex is the articulation point"
return 1;
temp = temp->next;
}
return 0;
}
4.3)printing results:
DFS应用——找出无向图的割点的更多相关文章
- lintcode:Find the Connected Component in the Undirected Graph 找出无向图汇总的相连要素
题目: 找出无向图汇总的相连要素 请找出无向图中相连要素的个数. 图中的每个节点包含其邻居的 1 个标签和 1 个列表.(一个无向图的相连节点(或节点)是一个子图,其中任意两个顶点通过路径相连,且不与 ...
- 310. Minimum Height Trees -- 找出无向图中以哪些节点为根,树的深度最小
For a undirected graph with tree characteristics, we can choose any node as the root. The result gra ...
- hdu1298 T9(手机输入法,每按一个数字,找出出现频率最高的字串,字典树+DFS)
Problem Description A while ago it was quite cumbersome to create a message for the Short Message Se ...
- HDU——3786找出直系亲属(DFS+回溯)
找出直系亲属 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...
- 『Tarjan算法 无向图的割点与割边』
无向图的割点与割边 定义:给定无相连通图\(G=(V,E)\) 若对于\(x \in V\),从图中删去节点\(x\)以及所有与\(x\)关联的边后,\(G\)分裂为两个或以上不连通的子图,则称\(x ...
- 求 无向图的割点和桥,Tarjan模板
/* 求 无向图的割点和桥 可以找出割点和桥,求删掉每个点后增加的连通块. 需要注意重边的处理,可以先用矩阵存,再转邻接表,或者进行判重 */ const int MAXN = 10010; cons ...
- UVA 315 Network (模板题)(无向图求割点)
<题目链接> 题目大意: 给出一个无向图,求出其中的割点数量. 解题分析: 无向图求割点模板题. 一个顶点u是割点,当且仅当满足 (1) u为树根,且u有多于一个子树. (2) u不为树根 ...
- Tarjan无向图的割点和桥(割边)全网详解&算法笔记&通俗易懂
更好的阅读体验&惊喜&原文链接 感谢@yxc的腿部挂件 大佬,指出本文不够严谨的地方,万分感谢! Tarjan无向图的割点和桥(割边) 导言 在掌握这个算法前,咱们有几个先决条件. [ ...
- 给出两个单词(start和end)与一个字典,找出从start到end的最短转换序列
问题 给出两个单词(start和end)与一个字典,找出从start到end的最短转换序列.规则如下: 一次只能改变一个字母 中间单词必须在字典里存在 例如: 给出 start = "hit ...
随机推荐
- 个人博客 V0.0.3 版本 ...
早就想弄个人博客网站,一直拖到现在...事情总是忙不完的,想能力提升的快,只能挤时间多练多写了,Keep On Unsleeping 以后原创的笔记都会在自己的博客网站写,博客园和简书就用来转发文章了 ...
- JavaScript继承(图解笔记)
JavaScript有多种继承模式,总结起来用到的方法有:原型链的传递.构造函数的借用.对象的复制. 对于原型链和原型的解释,可参考:JavaScript 原型中的哲学思想这篇文章讲得很清晰,让我 ...
- fuser 和 lsof
FUSER fuser功能fuser 可以显示出当前哪个程序在使用磁盘上的某个文件.挂载点.甚至网络端口,并给出程序进程的详细信息. fuser显示使用指定文件或者文件系统的进程ID.默认情况下每个文 ...
- Springboot集成BeanValidation扩展一:错误提示信息加公共模板
Bean Validator扩展 1.需求 在使用validator时,有个需求就是公用错误提示信息,什么意思? 举个例子: @NotEmpty非空判断,在资源文件中我不想每个非空判断都写”不 ...
- iOS教程:如何使用Core Data – 预加载和引入数据
这是接着上一次<iOS教程:Core Data数据持久性存储基础教程>的后续教程,程序也会使用上一次制作完成的. 再上一个教程中,我们只做了一个数据模型,之后我们使用这个数据模型中的数据创 ...
- 如何评价 GitHub 发布的文本编辑器 Atom?
这里是HN上的讨论:GitHub's new text editor leaked on Twitter这里是github page:Atom · GitHub 好多repo啊我不知道有没有知友了解更 ...
- Xamarin.Forms 调用腾讯地图
用Xamarin.Forms 也有一段时间了,跨平台,生成native代码的噱头 天花乱坠的, 其中的坑,只有用过的人才懂... 就拿地图来说...总不能用google地图吧 于是只能自己想办法了. ...
- README.md文档
大标题 =================================== 大标题一般显示工程名,类似html的\<h1\> 你只要在标题下面跟上=====即可 中标题 ------- ...
- component-scan和annotation-driven
<context:component-scan/> 该xml配置作用是启动Spring的组件扫描功能,自动扫描base-package指定的包及其子文件下的java文件,如果扫描到有@co ...
- mkdir的参数-p的作用
mkdir -p /nfs 也就是加上-p参数,之前只知道是递归创建目录,于是就发问了,得到的答案是: -p, --parents no error if existing, ...