【转】【模板】求割点和桥

【要求】给定一个无向图,找出图中的割点个桥

【说在前面】看了这么多,想入门理解的话真心推荐“听雨草堂”这一篇,结合模板以及各数组表示的含义看,至少把我看懂了。          模板我没用她的,用的是上交红书的模板,反正都一样的东西;

【几个定义】

  

  • DFS搜索树:用DFS对图进行遍历时,按照遍历次序的不同,我们可以得到一棵DFS搜索树,如图(b)所示。
  • 树边:(或称父子边),在搜索树中的实线所示,可理解为在DFS过程中访问未访问节点时所经过的边。
  • 回边:(或称返祖边后向边),在搜索树中的虚线所示,可理解为在DFS过程中遇到已访问节点时所经过的边。

【重点】基于DFS的算法 ---> Tarjan

  1. 对根节点u,若其有两棵或两棵以上的子树,则该根结点u为割点;
  2. 对非叶子节点u(非根节点),若其子树的节点均没有指向u的祖先节点的回边,说明删除u之后,根结点与u的子树的节点不再连通;则节点u为割点。

  cur是割点的条件:①cur是根且有大于一个儿子;  ②cur不是根且cur有一个儿子v使low[v] >= dfn[cur];、
  (cur, i)是桥的条件:low[i] > dfn[cur];

【难点】 对于dfn[MAX_V]与low[MAX_V]数组的理解与模拟其实现过程;

int dfn[MAX_V]; //结点v被访问时的深度
int low[MAX_V]; //结点v可以到达的访问时间最早的祖先的深度

详细示例见原博主;

【模板】

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<vector>
 5 #include<iostream>
 6 using namespace std;
 7 const int MAX_V = 1000;
 8 const int MAX_E = 1000000;
 9
10 int vis[MAX_V]; //结点v当前访问状态,0表示未访问,1表示在栈中,2表示已经访问过
11 int dfn[MAX_V]; //结点v被访问时的深度
12 int low[MAX_V]; //结点v可以到达的访问时间最早的祖先的深度
13 bool cut[MAX_V];
14 bool bridge[MAX_V][MAX_V];
15 //cur是割点的条件:①cur是根且有大于一个儿子; ②cur不是根且cur有一个儿子v使low[v]>=dfn[cur];
16 //(cur, i)是桥的条件:low[i] > dfn[cur];
17 void cur_bridge(int cur, int father, int dep, int n) //vertex: 0~n-1
18 {
19     vis[cur] = 1;
20     dfn[cur] = dep;
21     low[cur] = dep;
22     int children = 0;
23     for(int i = 0; i < n; i++)
24     {
25         if(edge[cur][i]) //与当前节点相连的结点i
26         {
27             if(i != father && vis[i] == 1) //i在当前栈中,说明图中有一个环,用i的深度更新cur的low值;
28             {
29                 if(dfn[i] < low[cur]) low[cur] = dfn[i]; //将结点cur可以到达的访问时间最早的祖先的深度更新为结点i被访问时的深度;
30             }
31             if(vis[i] == 0) //i没被访问过,递归访问节点i,并用i的可以到达的最早祖先来更新cur的low值;
32             {
33                 cut_bridge(i, cur, dep+1, n);
34                 children ++;
35
36                 if(low[i] < low[cur]) low[cur] = low[i];
37                 if((father == -1 && children > 1) || (father == -1 && low[i] >= dfn[cur]) //判断割点
38                    cut[cur] = true;
39                 if(low[i] > dfn[cut]) bridge[cur][i] = bridge[i][cur] = true;             //判断桥
40             }
41         }
42     }
43     vis[cur] = 2;
44 }
时间: 2024-10-13 01:38:02

【转】【模板】求割点和桥的相关文章

tarjan双联通求割点和桥模板

  求割点 int n,m,stamp,low[1005],dfn[1005],iscut[1005];//iscut记录的为割点 vector<int> vec[1005]; void tarjan(int index,int fa){ int child=0; low[index]=dfn[index]=++stamp; for(int i=0;i<vec[index].size();i++) { int tmp=vec[index][i]; if(!dfn[tmp]) { chil

求割点与桥

在学习了刘汝佳大大的蓝书后有点体会,特来小结一下. 割点:对于无向图G,如果删除某个点u后,连通分量数目增加,称u为图的割点. 桥:对于无向图G,如果删除某条边(u,v)后,连通分量数目增加,称(u,v)为图的桥. 先说说怎么求割点吧,我们可以先想怎么暴力求解:把每一个点删除一次,然后dfs看连通分量的数目的变化,不过这样复杂度O(n(n + m)),能不能优化呢?先想象一下割点是一个什么样的点: 其中A很显然是割点,D不是割点,这两个点很有特点,所以我们拿它们来分析,这个图很像一棵树,其中A是

tarjan求割点与桥——例题(9018——2100)

#include<cstdio> #include<iostream> #include<cstring> #include<vector> using namespace std; inline int read(){ int num=0,t=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();} while(c<='9'&&c>='0

【求无向图的桥,有重边】ZOJ - 2588 Burning Bridges

模板题——求割点与桥 题意,要使一个无向图不连通,输出必定要删掉的边的数量及其编号.求桥的裸题,可拿来练手. 套模板的时候注意本题两节点之间可能有多条边,而模板是不判重边的,所以直接套模板的话,会将重边也当做桥输出,因此要在判断桥的时候加一个判断,即当且仅当两点之间仅有一条边,且满足dfn[cur] < low[i],(cur, i)才是桥. 另外本题节点数为105,用邻接矩阵的话会内存超限,所以我用了了一个multiset存储边及其编号. 代码如下: 1 #include<cstdio>

求割点 割边 Tarjan

附上一般讲得不错的博客 https://blog.csdn.net/lw277232240/article/details/73251092 https://www.cnblogs.com/collectionne/p/6847240.html https://blog.csdn.net/zhn_666/article/details/77971619 然后附上模板题:              https://vjudge.net/problem/HihoCoder-1183 裸题,直接要你输

图的割点、桥与双连通分支

原文地址:图的割点.桥与双连通分支 [点连通度与边连通度] 在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合.一个图的点连通度的定义为,最小割点集合中的顶点数. 类似的,如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合.一个图的边连通度的定义为,最小割边集合中的边数. [双连通图.割点与桥] 如果一个无向连通图的点连通度大于1,则称该图是点双连通的(point biconne

强连通分量、割点、桥

一.强连通分量 在有向图G中,如果任意两个不同的顶点相互可达,则该有向图为强连通的:一个有向图G的极大连通子图称为G的强连通分支:将有向图G的每一条边反向形成的图称为G的转置 Gt. 1.1 有向图的一些定理 有向无环图中唯一出度为0的点,一定可以由任何点出发到达     图中节点的数目为有限多个,而且无环,因此从任何点出发往前走,一定终止于出度为0的点,否则走N+1步(N为图中节点的数目),则必然有一个点被走了两次,形成了环,与无环矛盾! 有向无环图中所有入度不为0的点,一定可以由某个入度为0

【转载】图的割点、桥与双连通分支

[点连通度与边连通度] 在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合.一个图的点连通度的定义为,最小割点集合中的顶点数. 类似的,如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合.一个图的边连通度的定义为,最小割边集合中的边数. [双连通图.割点与桥] 如果一个无向连通图的点连通度大于1,则称该图是点双连通的(point biconnected),简称双连通或重连通.一个

【转】图的割点、桥与双连通分支

原文地址:https://www.byvoid.com/blog/biconnect 图的割点.桥与双连通分支 [点连通度与边连通度] 在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合.一个图的点连通度的定义为,最小割点集合中的顶点数. 类似的,如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合.一个图的边连通度的定义为,最小割边集合中的边数. [双连通图.割点与桥] 如果一个