【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 vertexvertexIndex[vertex] = counter++; // evaluating vertex index with countervertexLow[vertex] = vertexIndex[vertex]; // the 1st rule: evaluating vertex low with countertemp = 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 effectfor(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 graphvertexLow[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 backsideelse {parent[adjVertex] = vertex;         // just for printing effectfor(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应用——找出无向图的割点相关推荐

  1. c语言tarjan算法,无向图求割点和割边——Tarjan算法

    无向图中求割点集和割边集--Tarjan算法 割点和割边 定义 在一个无向图中,如果删除了某个顶点及与之相连的所有边,产生了一更大连通分量的子图,这样的顶点被称为割点或关节点.对于一个图的所有割点的集 ...

  2. tarjan算法求无向图的割点和桥

    tarjan算法求无向图的割点与桥 一篇tarjan算法求割点与桥的完整的解释,写的真的好认真 以下代码来自kuangbin的模板 4.5 图的割点.桥和双连通分支的基本概念 [点连通度与边连通度] ...

  3. 31 | 深度和广度优先搜索:如何找出社交网络中的三度好友关系?

    问题导入 给你一个用户,如何找出这个用户的所有三度(其中包含一度.二度和三度)好友关系? 搜索算法 算法是作用于具体数据结构之上的,深度优先搜索算法和广度优先搜索算法都是基于"图" ...

  4. CodeForces - 1364D Ehabs Last Corollary(dfs树找最小环)

    题目链接:点击查看 题目大意:给出一个由 n 个结点和 m 条边构成的无向图,再给出一个 k ,需要在图中完成下面任意一种操作: 找到一个大小恰好为  的独立集 找到一个大小不超过 k 的环 题目分析 ...

  5. Python-图-如何找出社交网络中的三度好友关系

    羁绊前行的,不是肆虐的狂风,而是内心的迷茫.-王争. 最近有些偷懒,距离上次更新也有两个星期了,原因我也很清楚,就是又开始有些迷茫了,购买了不少课程,仍不能减轻内心的焦虑.焦虑的原因还是想得太多,做得 ...

  6. 常考数据结构与算法----给定一个二叉树和一个值 sum,请找出所有的根节点到叶子节点的节点值之和等于sum 的路径,

    题目描述 给定一个二叉树和一个值sum,请找出所有的根节点到叶子节点的节点值之和等于sum 的路径, 例如: 给出如下的二叉树,sum=22, 返回 [ [5,4,11,2], [5,8,9] ] 示 ...

  7. [LeetCode]Palindrome Partitioning 找出所有可能的组合回文

    给定一个字符串,切割字符串,这样每个子字符串是一个回文字符串. 要找出所有可能的组合. 办法:暴力搜索+回溯 class Solution { public:int *b,n;vector<ve ...

  8. 数字n,按字典排序,找出第k小的数字

    (1)首先列出所有的字典序,然后选择第k个 class Solution { public:     bool static compare(int a,int b)     {         re ...

  9. HDU3534 给你一个树让你找出其中最长路径以及个数数

    Description In the Datastructure class of HEU, the teacher asks one problem: How to find the longest ...

最新文章

  1. 单步调试_keil for arm 调试时无法单步运行及打断点
  2. leetcode算法题--Letter Case Permutation
  3. 60分钟快速入门 PyTorch
  4. 改进初学者的PID-初始化
  5. javascrpt 继承
  6. 取余运算怎么算_3 数学运算 矩阵操作
  7. java实现第五届蓝桥杯出栈次序
  8. SEM测试样品减薄及表面复型
  9. flask 将route放置在多个文件中的方法(蓝本)
  10. Python 预测基因变异是否具有相互冲突的临床分类问题
  11. 零基础学UI设计难吗?
  12. Apache日志分割及分析
  13. python密码游戏
  14. python二级第七套答案
  15. 论文笔记:Editing-Based SQL Query Generation for Cross-Domain Context-Dependent Questions
  16. 被查封7周之后,全球最大BT网站“海盗湾”又重新活过来了【36kr】
  17. Codeforces 91A Newspaper Headline
  18. 四轮移动机器人(阿克曼底盘)数学建模
  19. MiiX·阿希全球区块链黑客马拉松大赛 获奖选手专访
  20. PHP画a梦,html打造动漫人物--哆啦A梦

热门文章

  1. Codeforces Round #556 (Div. 1Div. 2)
  2. 牛客网【每日一题】7月31日题目精讲—兔子的区间密码
  3. [骗分技巧——随机化Ⅰ]CodeChef-Milestones,CF364D-Ghd
  4. P1232-[NOI2013]树的计数【思维】
  5. hdu5909-Tree Cutting【FWT】
  6. P4318,bzoj2440-完全平方数【二分答案,莫比乌斯函数,容斥】
  7. P1600-天天爱跑步【LCA,桶,树上差分】
  8. 2018/7/19-纪中某C组题【jzoj3461,jzoj3462,jzoj3463,jzoj3464】
  9. 【DP】【树状数组】方伯伯的玉米田/优美玉米(luogu 3287/金牌导航 数据结构优化DP-5)
  10. 【矩阵乘法】沼泽鳄鱼(ssl 2511)