无向图的割顶和桥的性质 以及双连通分量的求解算法

割顶:对于无向图G,如果删除某个点u后,连通分量的数目增加, 称u为图的割顶。对于连通图,割顶就是删除之后使图不再连通的点。

割顶的求解依如下定理:

  在无向连通图G的DFS树中,非根结点u是G的割顶当且仅当u存在一个子节点v,使得v及其所有后代都没有反向边连回u的祖先(连回u)不算。

算法实现:

  采用时间戳,在dfs遍历的过程中给每个节点u均标记以前序时间戳pre[u],设low[u]为u及其后代所能连回的最早的祖先的pre值,则定理中的条件就可以简写成结点u存在一个子结点v,使得 low[v] >= pre[u]

  作为一种特殊情况,如果v的后代只能连回v自己,即 low[v] > pre[u] ,只需要删除边(u, v) 就可以让G非连通了,满足这个条件的边称为桥。换句话说,我们不仅知道结点u是割顶,还知道了(u, v)是桥。

双连通分量:

  对于一个连通图,如果任意两点至少存在两条点不重复的路径,则说这个图是点-双连通的。即任意两条边都在同一个简单环内

  如果任意两点至少存在两条边不重复的路径,则说这个图是边-双连通的。即每条边都至少在一个简单环中

  对于一张无向图,点-双连通的极大子图称为双连通分量(BCC)。

性质:

  1.每条边恰好属于一个双连通分量。

  2.不同双连通分量最多只有一个公共点,且它一定是割顶。

  3.任意割顶都是至少两个不同双连通分量的公共点。

  4.桥不属于任何边-双连通分量,除了桥的每条边恰好属于一个边-双连通分量。

计算点-双连通分量的算法:

 1 int n;
 2 int pre[maxn], bccno[maxn], iscut[maxn], dfs_clock, bcc_cnt;
 3 vector<int> G[maxn], bcc[maxn];
 4
 5 struct Edge{
 6     int u, v;
 7     Edge(int uu, int vv): u(uu), v(vv) {}
 8 };
 9
10 stack<Edge> S;
11
12 int dfs(int u, int fa) {
13     int lowu = pre[u] = ++dfs_clock;  //时间戳
14     int child = 0;            //子结点数目
15     for(int i = 0; i < G[u].size(); i++) {
16         int v = G[u][i];
17         Edge e = Edge(u, v);
18         if(!pre[v]) {          //没有访问过v
19             child++;
20             S.push(e);
21             int lowv = dfs(v, u);
22             lowu = min(lowu, lowv);
23             if(lowv >= pre[u]) {
24                 iscut[u] = 1;
25                 bcc[++bcc_cnt].clear();
26                 for(;;) {
27                     Edge x = S.top(); S.pop();
28                     if(bccno[x.u] != bcc_cnt) {bcc[bcc_cnt].push_back(x.u); bccno[x.u] = bcc_cnt;}
29                     if(bccno[x.v] != bcc_cnt) {bcc[bcc_cnt].push_back(x.v); bccno[x.v] = bcc_cnt;}
30                     if(x.u == u && x.v == v) break;
31                 }
32             }
33         }
34         else if(pre[v] < pre[u] && v != fa) {
35             child++;
36             S.push(e);
37             lowu = min(lowu, pre[v]);
38         }
39     }
40     if(fa < 0 && child == 1) iscut[u] = 0;
41     return lowu;
42 }
43
44 void find_bcc() {
45     memset(pre, 0, sizeof pre);
46     memset(bccno, 0, sizeof bccno);
47     memset(iscut, 0, sizeof iscut);
48     dfs_clock = bcc_cnt = 0;
49     for(int u = 0; u < n; u++) if(pre[u] == 0) dfs(u, -1);
50 }
时间: 2024-12-21 05:14:23

无向图的割顶和桥的性质 以及双连通分量的求解算法的相关文章

连通分量 无向图的割顶和桥 无向图的双连通分量 有向图的强连通分量

时间戳 dfs_clock :说白了就是记录下访问每个结点的次序.假设我们用 pre 保存,那么如果 pre[u] > pre[v], 那么就可以知道先访问的 v ,后访问的 u . 现在给定一条边, (u, v), 且 u 的祖先为 fa, 如果有 pre[v] < pre[u] && v != fa, 那么 (u, v) 为一条反向边. 1 求连通分量: 相互可达的节点称为一个连通分量: #include <iostream> #include <cstd

无向图求割顶与桥

无向图求割顶与桥 对于无向图G,如果删除某个点u后,连通分量数目增加,称u为图的关节点或割顶.对于连通图,割顶就是删除之后使图不再连通的点.如果删除边(u,v)一条边,就可以让连通图变成不连通的,那么边(u,v)是桥. 具体的概念和定义比较多,在刘汝佳<<训练指南>>P312-314页都有详细的介绍. 下面来写求无向图割顶和桥的DFS函数.我们令pre[i]表示第一次访问i点的时间戳,令low[i]表示i节点及其后代所能连回(通过反向边)的最早祖先的pre值. 下面的dfs函数返回

无向图的割顶和桥,无向图的双连通分量入门详解及模板 -----「转载」

https://blog.csdn.net/stillxjy/article/details/70176689 割顶和桥:对于无向图G,如果删除某个节点u后,连通分量数目增加,则称u为图的割顶:如果删除某条边后,连通分量数目增加,则称该边为图的桥.对于连通图删除割顶或桥后都会使得图不再连通 以下我,我们利用dfs的性质来快速找出一个连通图中的所有的割顶和桥 首先我们要引入”时间戳”这个概念: 时间戳:表示在进行dfs时,每个节点被访问的先后顺序.每个节点会被标记两次,分别用pre[],和post

无向图的割顶和桥

割顶: 关键点,删掉这个点后,图的连通分量 + 1: 桥: 在割顶的基础上,发现删除 (u,v) 这条边,图就变成非连通的了. 如何找出所有割顶和桥: 时间戳: 在无向图的基础上,DFS建树的过程中,各点进栈和出栈的时间 dfs_clock,进栈的时间 pre[],出栈的时间 post[] 在DFS程序中的体现就是: void previst(int u) { pre[u]= ++dfs_clock; } void postvist(int u) { post[u] = ++dfs_clock;

DFS的运用(二分图判定、无向图的割顶和桥,双连通分量,有向图的强连通分量)

一.dfs框架: 1 vector<int>G[maxn]; //存图 2 int vis[maxn]; //节点访问标记 3 void dfs(int u) 4 { 5 vis[u] = 1; 6 PREVISIT(u); //访问节点u之前的操作 7 int d = G[u].size(); 8 for(int i = 0; i < d; i++)//枚举每条边 9 { 10 int v = G[u][i]; 11 if(!vis[v])dfs(v); 12 } 13 POSTVIS

无向图的割顶和桥(tarjan模板)

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define maxn 7500 #define inf 0x3f3f3f3f int first[maxn],to[maxn],nxt[maxn],e; int pre[maxn],low[maxn]; int clock; int iscut[maxn]; void

无向图求割顶和桥总结

1.求能够分成几个联通分量什么的一般都在dfs中间那里if(...>...) cnt[i],iscut[i]维护一下就OK了. 2.根结点特别需要注意. 好像就没了→_→

Tarjan 算法求无向图的割顶和桥

#include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int N = 250; int head[N], low[N], dfn[N], fa[N]; int n, m, now = 1, Tarjan_clock; bool is_cut[N]; struct Node{ int u, v, nxt; }E[N]; inline int read()

2018/2/11 每日一学 无向图割顶和桥

割顶和桥:对于无向图G,如果删除某个节点u后,连通分量数目增加,则称u为图的割顶:如果删除某条边后,连通分量数目增加,则称该边为图的桥. 对于连通图删除割顶或桥后都会使得图不再连通. 我们利用dfs的性质来快速找出一个连通图中的所有的割顶和桥. 设low[u]为u及其后代所能连回的最早的祖先的pre[]值,pre[]为时间戳则当u存在一个子节点v使得low[v] >= pre[u]时u就为割顶 同理当 low[v] > pre[u]时 u-v为桥 看代码吧(转自http://blog.csdn