无向图割边割点算法

而当(u,v)为树边且low[v]>dfn[u]时,表示v节点只能通过该边(u,v)与u连通,那么(u,v)即为割边。

 1 void dfs(int u) {
 2     //记录dfs遍历次序
 3     static int counter = 0;
 4
 5     //记录节点u的子树数
 6     int children = 0;
 7
 8     ArcNode *p = graph[u].firstArc;
 9     visit[u] = 1;
10
11     //初始化dfn与low
12     dfn[u] = low[u] = ++counter;
13
14     for(; p != NULL; p = p->next) {
15         int v = p->adjvex;
16
17         //节点v未被访问,则(u,v)为树边
18         if(!visit[v]) {
19             children++;
20             parent[v] = u;
21             dfs(v);
22
23             low[u] = min(low[u], low[v]);
24
25             //case (1)
26             if(parent[u] == NIL && children > 1) {
27                 printf("articulation point: %d\n", u);
28             }
29
30             //case (2)
31             if(parent[u] != NIL && low[v] >= dfn[u]) {
32                 printf("articulation point: %d\n", u);
33             }
34
35             //bridge
36             if(low[v] > dfn[u]) {
37                 printf("bridge: %d %d\n", u, v);
38             }
39         }
40
41         //节点v已访问,则(u,v)为回边
42         else if(v != parent[u]) {
43             low[u] = min(low[u], dfn[v]);
44         }
45     }
46 }

View Code

边双联通分量算法

对于一个无向图的子图,当删除其中任意一个点后,不改变图内点的连通性,这样的子图叫做点的双连通子图。而当子图的边数达到最大时,叫做点的双连通分量。

直观的做法自然先用上周的算法求出所有桥,去掉所有桥之后再做DFS求出每一个连通子图。我们这周要介绍一种更"抽象"的算法,通过在Tarjan算法当中巧妙地用一个栈来统计出每一个组内的节点,其代码如下:

 1 void dfs(int u) {
 2     //记录dfs遍历次序
 3     static int counter = 0;
 4
 5     //记录节点u的子树数
 6     int children = 0;
 7
 8     ArcNode *p = graph[u].firstArc;
 9     visit[u] = 1;
10
11     //初始化dfn与low
12     dfn[u] = low[u] = ++counter;
13
14     //将u加入栈
15     stack[++top] = u;
16
17     for(; p != NULL; p = p->next) {
18         int v = p->adjvex;
19
20         //节点v未被访问,则(u,v)为树边
21         if(!visit[v]) {
22             children++;
23             parent[v] = u;
24             dfs(v);
25
26             low[u] = min(low[u], low[v]);
27             if (low[v] > dfn[u]) {
28                 printf("bridge: %d %d\n", u, v);    // 该边是桥
29                 bridgeCnt++;
30             }
31         }
32
33         //节点v已访问,则(u,v)为回边
34         else if(v != parent[u]) {
35             low[u] = min(low[u], dfn[v]);
36         }
37     }
38
39     if (low[u] == dfn[u])
40     {
41         // 因为low[u] == dfn[u],对(parent[u],u)来说有dfn[u] > dfn[ parent[u] ],因此low[u] > dfn[ parent[u] ]
42         // 所以(parent[u],u)一定是一个桥,那么此时栈内在u之前入栈的点和u被该桥分割开
43         // 则u和之后入栈的节点属于同一个组
44         将从u到栈顶所有的元素标记为一个组,并弹出这些元素。
45     }
46 }

View Code

强连通分量

对于有向图上的2个点a,b,若存在一条从a到b的路径,也存在一条从b到a的路径,那么称a,b是强连通的。
对于有向图上的一个子图,若子图内任意点对(a,b)都满足强连通,则称该子图为强连通子图。
非强连通图有向图的极大强连通子图,称为强连通分量。
特别地,和任何一个点都不强连通的单个点也是一个强连通分量。

 1 tarjan(u)
 2 {
 3     Dfn[u]=Low[u]=++Index                      // 为节点u设定次序编号和Low初值
 4     Stack.push(u)                              // 将节点u压入栈中
 5     for each (u, v) in E                       // 枚举每一条边
 6         if (v is not visted)                   // 如果节点v未被访问过
 7             tarjan(v)                          // 继续向下找
 8             Low[u] = min(Low[u], Low[v])
 9         else if (v in Stack)                   // 如果节点v还在栈内(很重要,无向图没有这一步)
10             Low[u] = min(Low[u], Dfn[v])
11     if (Dfn[u] == Low[u])                      // 如果节点u是强连通分量的根
12         repeat
13             v = Stack.pop                      // 将v退栈,为该强连通分量中一个顶点
14             mark v                             // 标记v,同样通过栈来找连通分量
15         until (u == v)
16 }

View Code

scc + 缩点 + topo

点的双连通分量

对于一个无向图的子图,当删除其中任意一个点后,不改变图内点的连通性,这样的子图叫做点的双连通子图。而当子图的边数达到最大时,叫做点的双连通分量。

                                       

对于桥的两种情况,它分割个区域数刚好就等于割点数+1;而连通分量内的割点同样也是,每存在一个割点,点的双连通分量就增加一个。

点的双连通分量就等于割点数量加1。

每存在一个割点,就把一个区域一分为二,所以最后的结果也就是统计割点的数量就可以了。而对于分组具体情况,我们仍然采用栈来辅助我们记录

 1 void dfs(int u) {
 2     //记录dfs遍历次序
 3     static int counter = 0;
 4
 5     //记录节点u的子树数
 6     int children = 0;
 7
 8     ArcNode *p = graph[u].firstArc;
 9     visit[u] = 1;
10
11     //初始化dfn与low
12     dfn[u] = low[u] = ++counter;
13
14     for(; p != NULL; p = p->next) {
15         int v = p->adjvex;
16         if(edge(u,v)已经被标记) continue;
17
18         //节点v未被访问,则(u,v)为树边
19         if(!visit[v]) {
20             children++;
21             parent[v] = u;
22             edgeStack[top++] = edge(u,v); // 将边入栈
23             dfs(v);
24
25             low[u] = min(low[u], low[v]);
26
27             //case (1)
28             if(parent[u] == NIL && children > 1) {
29                 printf("articulation point: %d\n", u);
30                 // mark edge
31                 // 将边出栈,直到当前边出栈为止,这些边标记为同一个组
32                 do {
33                     nowEdge = edgeStack[top];
34                     top--;
35                     // 标记nowEdge
36                 }    while (nowEdge != edge(u,v))
37             }
38
39             //case (2)
40             if(parent[u] != NIL && low[v] >= dfn[u]) {
41                 printf("articulation point: %d\n", u);
42                 // mark edge
43                 // 将边出栈,直到当前边出栈为止,这些边标记为同一个组
44                 do {
45                     nowEdge = edgeStack[top];
46                     top--;
47                     // 标记nowEdge
48                 }    while (nowEdge != edge(u,v))
49             }
50
51         }
52
53         //节点v已访问,则(u,v)为回边
54         else if(v != parent[u]) {
55             edgeStack[top++] = edge(u,v);
56             low[u] = min(low[u], dfn[v]);
57         }
58     }
59 }

View Code

转载于:https://www.cnblogs.com/usedrosee/p/4693121.html

hiho图的联通性(自留)相关推荐

  1. 图论 ---- E. Bear and Forgotten Tree 2(判补图的联通性技巧 图遍历的优化 条件拆分)

    题目大意 题目大意: 给你nnn个点,mmm对关系表示(ai,bi)(a_i,b_i)(ai​,bi​)之间是没有边的问你能否构建出一颗树满足111号点的度数为kkk? 解题思路: 如果没有后面的条件 ...

  2. 2018十二月刷题列表

    Preface \(2018\)年的尾巴,不禁感慨自己这一年的蜕变只能用蜕变来形容了. 而且老叶说我们今年没的参加清北冬令营可以参加CCF在广州二中举办的冬令营,只要联赛\(390+\)就应该可以报. ...

  3. 几何深度学习(Geometric Deep Learning)技术

    几何深度学习(Geometric Deep Learning)技术 几何深度学习综述 从论文Geometric Deep Learning: Grids, Groups, Graphs, Geodes ...

  4. 最小割 ---- 二分图最大独立集(集合冲突模型) ---- 骑士共存 方格取数(网络流24题)

    二分图独立集 定理: 二分图最大独立集=n - 二分图最大匹配 其实二分图独立集是特殊的一种最大权闭合子图.我们根据上文"收益"的思想,把选某个点的收益看为1,左部节点为正权点,右 ...

  5. Michael Brostein 最新几何深度学习综述:超越 WL 和原始消息传递的 GNN

    来源:AI科技评论 本文约8500字,建议阅读15+分钟 本文叫你如何突破基于 WL 测试和消息传递机制的 GNN 的性能瓶颈. 图可以方便地抽象关系和交互的复杂系统.社交网络.高能物理.化学等研究领 ...

  6. Attack on Alpha-Zet

    题目链接:https://nanti.jisuanke.com/t/28852 7998: Attack on Alpha-Zet 时间限制: 1 Sec  内存限制: 512 MB 提交: 28   ...

  7. 东北电力大学计算机网络复试题,2020年东北电力大学计算机学院复试(20200901201159).pdf...

    复试科目考试大纲 "数据结构"考试大纲 一.考试的学科范围 数据结构课程教学(大纲)基本要求的所有内容. 二.评价目标 主要考查考生对数据结构课程的基础理论. 基本知识掌握和运用的 ...

  8. Popular Cows POJ - 2186(tarjan算法)+详解

    题意: 每一头牛的愿望就是变成一头最受欢迎的牛.现在有 N头牛,给你M对整数(A,B),表示牛 A认为牛B受欢迎.这种关系是具有传递性的,如果 A认为 B受欢迎, B认为 C受欢迎,那么牛 A也认为牛 ...

  9. P6378 [PA2010] Riddle(2-sat/前后缀优化建图)

    P6378 [PA2010] Riddle n个点m条边的无向图,分为k个部分,从每个部分选择恰好一个关键点,使得每条边至少有一个端点是关键点. 首先有这么多的限制,实际上就是一个选或者不选的问题,每 ...

最新文章

  1. python打印空心平行四边形的面积公式_打印等腰三角形和空心平行四边形
  2. 下载keep运动软件_我把私教带回了家,Keep智能动感单车体验|钛极客
  3. c语言中热河输入空格,承德市2020年(春秋版)小学英语六年级上册期中考试模拟试卷(1)C卷...
  4. Mybatis实现CRUD操作
  5. idea 快速导入实现父类方法_网站seo优化方法,实现快速排名!
  6. 学MFC的九九八十一难
  7. 【[Offer收割]编程练习赛10 C】区间价值
  8. redis雪崩和穿透、击穿的解决方法
  9. 1487: [HNOI2009]无归岛
  10. Word插入脚注只占左下角一栏的方法
  11. amos看拟合度在哪里看_Amos软件完结篇!模型无法拟合,拟合指标不佳如何解决?...
  12. [趣味文学]“帅气”的莎士比亚
  13. 逻辑回归实例,特征预处理
  14. erlang使用httpc:request报错nxdomain
  15. VSPD+XCOM+Proteus仿真stm32串口通信
  16. 盲签名——典型的数字签名技术
  17. 安卓apache php mysql_Android下安装apache、mysql、php环境
  18. 计算机视觉编程——基本的图像操作和处理
  19. 2021 软件测试工具大全
  20. Cython配置安装(ubuntu)

热门文章

  1. mysql教程目录_MySql目录(二)
  2. android studio gradle 学习,学习Android Studio里的Gradle
  3. linux root邮箱地址,linux – 如何将root的电子邮件转发到外部电子邮件地址?
  4. td 双击 编辑 php,双击表格td进行编辑
  5. c语言箭头指针的作用,C语言中,结构体成员变量的点和箭头
  6. go 语言 first argument to append must be slice
  7. linux ftp日志_linux学习笔记(一)——Linux分区和目录结构
  8. flutter生成源代码_Flutter创建工程的主要代码详解
  9. [leetcode] 617. Merge Two Binary Trees
  10. uva 11490 ——Just Another Problem