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

Posted on 2015-08-13 21:32  LLGemini  阅读(1305)  评论(2编辑  收藏  举报

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

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

【几个定义】

  

  • 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 }