求无向图的割点和桥模板(tarjan)
2017-04-24 19:52
387 查看
一.基本概念
1.桥:若无向连通图的边割集中只有一条边,则称这条边为割边或者桥 (离散书上给出的定义。。
通俗的来说就是无向连通图中的某条边,删除后得到的新图联通分支至少为2(即不连通;
2.割点:若无向连通图的点割集中只有一个点,则称这个点为割点或者关节点 ;
通俗的来说就是无向连通图中的某条边,删除后得到的新图连通分支至少为2;
二:tarjan算法求割点和桥
1.割点:1)当前节点为树根的时候,条件是“要有多余一棵子树”;
如果这有一颗子树,去掉这个点也没有影响,如果有两颗子树,去掉这点,两颗子树就不连通了;
2)当前节点u不是树根的时候,条件是“low[v]>=dfn[u]”,也就是在u之后遍历的点,能够向上翻,
最多到u,如果能翻到u的上方,那就有环了,去掉u之后,图仍然连通。
2.桥:若一条无向边(u,v)是桥,
1)当且仅当无向边(u,v)是树枝边,需要满足dfn(u)<low(v),即v向上翻不到u及其以上的点,
那么u--v之间一定能够有1条或者多条边不能删去, 因为他们之间有部分无环,是桥,
如果v能上翻到u那么u--v就是一个环,删除其中一条路径后,仍然是连通的。
3.注意点:1)求桥的时候:因为边是无方向的,所以父亲孩子节点的关系需要自己规定一下,
在tarjan的过程中if(v不是u的父节点) low[u]=min(low[u],dfn[v]);
因为如果v是u的父亲,那么这条无向边就被误认为是环了。
2)找桥的时候:注意看看有没有重边,有重边的边一定不是桥,也要避免误判。
4.也可以先进行tarjan(),求出每一个点的dfn和low,并记录dfs过程中的每个点的父节点,
遍历所有点的low,dfn来寻找桥和割点
代码:
View Code
以上参考博客:http://www.cnblogs.com/c1299401227/p/5402747.html
1.桥:若无向连通图的边割集中只有一条边,则称这条边为割边或者桥 (离散书上给出的定义。。
通俗的来说就是无向连通图中的某条边,删除后得到的新图联通分支至少为2(即不连通;
2.割点:若无向连通图的点割集中只有一个点,则称这个点为割点或者关节点 ;
通俗的来说就是无向连通图中的某条边,删除后得到的新图连通分支至少为2;
二:tarjan算法求割点和桥
1.割点:1)当前节点为树根的时候,条件是“要有多余一棵子树”;
如果这有一颗子树,去掉这个点也没有影响,如果有两颗子树,去掉这点,两颗子树就不连通了;
2)当前节点u不是树根的时候,条件是“low[v]>=dfn[u]”,也就是在u之后遍历的点,能够向上翻,
最多到u,如果能翻到u的上方,那就有环了,去掉u之后,图仍然连通。
2.桥:若一条无向边(u,v)是桥,
1)当且仅当无向边(u,v)是树枝边,需要满足dfn(u)<low(v),即v向上翻不到u及其以上的点,
那么u--v之间一定能够有1条或者多条边不能删去, 因为他们之间有部分无环,是桥,
如果v能上翻到u那么u--v就是一个环,删除其中一条路径后,仍然是连通的。
3.注意点:1)求桥的时候:因为边是无方向的,所以父亲孩子节点的关系需要自己规定一下,
在tarjan的过程中if(v不是u的父节点) low[u]=min(low[u],dfn[v]);
因为如果v是u的父亲,那么这条无向边就被误认为是环了。
2)找桥的时候:注意看看有没有重边,有重边的边一定不是桥,也要避免误判。
4.也可以先进行tarjan(),求出每一个点的dfn和low,并记录dfs过程中的每个点的父节点,
遍历所有点的low,dfn来寻找桥和割点
代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 using namespace std; 5 6 const int MAXN = 1e5 + 10; 7 8 struct node{ 9 int v, next, use; 10 }edge[MAXN << 2]; 11 12 bool bridge[MAXN]; 13 int low[MAXN], dfn[MAXN], vis[MAXN]; 14 int head[MAXN], pre[MAXN], ip, sol, count; 15 16 void init(void){ 17 memset(head, -1, sizeof(head)); 18 memset(vis, false, sizeof(vis)); 19 memset(bridge, false, sizeof(bridge)); 20 count = sol = ip = 0; 21 } 22 23 void addedge(int u, int v){ 24 edge[ip].v = v; 25 edge[ip].use = 0; 26 edge[ip].next = head[u]; 27 head[u] = ip++; 28 } 29 30 void tarjan(int u){ 31 vis[u] = 1; 32 dfn[u] = low[u] = count++; 33 for(int i = head[u]; i != -1; i = edge[i].next){ 34 if(!edge[i].use){ 35 edge[i].use = edge[i ^ 1].use = 1; 36 int v = edge[i].v; 37 if(!vis[v]){ 38 pre[v] = u; 39 tarjan(v); 40 low[u] = min(low[u], low[v]); 41 if(dfn[u] < low[v]){ 42 sol++; 43 bridge[v] = true; 44 } 45 }else if(vis[v] == 1){ 46 low[u] = min(low[u], dfn[v]); 47 } 48 } 49 } 50 vis[u] = 2; 51 } 52 53 int main(void){ 54 int n, m, q, x, y, cas = 1; 55 while(~scanf("%d%d", &n, &m)){ 56 if(!n && !m) break; 57 init(); 58 for(int i = 0; i < m; i++){ 59 scanf("%d%d", &x, &y); 60 addedge(x, y); 61 addedge(y, x); 62 } 63 pre[1] = 1; 64 tarjan(1); 65 for(int i = 1; i <= n; i++){ 66 if(bridge[i]) cout << i << " " << pre[i] << endl; 67 } 68 } 69 return 0; 70 }
View Code
以上参考博客:http://www.cnblogs.com/c1299401227/p/5402747.html
相关文章推荐
- poj 2117 Electricity 求无向图中去掉一个点后最大的联通分支数 无向图有可能不联通 tarjan求割点模板
- POJ 1144 Network Tarjan 求无向图的割点的个数 Tarjan 模板题
- Network(特殊的输入格式+tarjan求割点模板题)
- POJ 1144 - Network 用tarjan求无向图的割点
- POJ 1523 SPF tarjan求割点模板
- tarjan求割点模板
- POJ1144 Network (Tarjan算法求无向图的割点)
- 796 Critical Links( 求无向图中的桥--模板)
- 无向图的点双连通分量(tarjan模板)
- 有向图tarjan 求桥 + 求SCC以及里面的点和它的入度 +缩点 模板 【总结】
- 无向图的割顶和桥(tarjan模板)
- 【关节点+桥】关节点和桥模板 Tarjan
- zoj3630 Information (tarjan) 模板 邻接表
- hdu 2874 lca-tarjan离线算法(模板)
- Tarjan模板 人工栈版Tarjan
- Tarjan算法--求无向图的割点和桥
- 求割点模板——Network
- HDU1289 Tarjan-模板题
- tarjan算法--求无向图的割点和桥
- HDU 1269 迷宫城堡【Tarjan强连通分量 模板】