关节点(atriculation point)算法

来源:互联网 发布:js animate transform 编辑:程序博客网 时间:2024/05/16 02:29

 

//求关节点(atriculation point)算法/** *某个顶点A时关节点必须满足下列条件之一 *1:A的是深度优先生成树的根,并且A子树的个数大于等于2。 *2:A不是深度优先生成树的根和叶子节点,并且A的子树根以及子树根的儿孙都没有指向A祖先的回边(回边就是在图中但不在生成树中的边)。 *//* *算法思想 *1:在深度优先遍历过程中,记录下每棵顶点访问的次序,在单纯的dfs中visited[MAX]数组用来标记一个顶点是否被访问过,但是在这里还用来记   录访问的次序,visited[i]>0表示此顶点已经被访问过并且访问的次序是visited[i]。  2:当判断A顶点是不是关节点的时候,需要知道需要知道A顶点的子树以及子树的儿孙时候有指向A顶点的祖先(即被访问的次序小于A的顶点就是AA的祖先),A顶点的子树及子树的儿孙可能有许多的回边指向A的祖先,我们需要求visted[A],low[w],visted[k]中最小的值就可以,这个最小的之就是A的low[A]值,low[MAX]数组用来记录某个顶点(包括这个顶点)以及这个顶点的儿孙中指向这个顶点的祖先顶点中最小的次序顶点。但是怎么求low[MAX]中的值呢?low[v]=min{visited[v],low[w](w为v的邻接点),visited[k](v到k的回边)},其中visited[v]和visited[k]可以很容易求得,  那low[w]怎么求呢?显然这里是递归的概念,求low[v]需要知道他的所有的子树根的low[w],同样求low[w]需要知道w的所有子树根的low[w'].  当low[w] >= visited[v]v必定是关节点 *///代码参考#include "stdio.h"#include "string.h"//图的邻接矩阵表示方法int Matrix[8][8] = {  /*a b c d e f g h*/  /*a*/{0,1,0,0,0,1,1,1},  /*b*/{1,0,1,0,0,0,0,0},  /*c*/{0,1,0,1,1,1,0,0},  /*d*/{0,0,1,0,1,0,0,0},  /*e*/{0,0,1,1,0,0,0,0},  /*f*/{1,0,1,0,0,0,0,0},  /*g*/{1,0,0,0,0,0,0,1},  /*h*/{1,0,0,0,0,0,1,0},};int count = 0;//当前有多少个顶点已经访问过int visited[10];//用来记录顶点访问的次序int low[10];int vertex_num = 8;//v顶点的下一个邻接点int next_adjacent_vertex (int v,int index) {int i;for (i = index;i < 8;i++) {if (1 == Matrix[v][i]) {return i;}} return -1;//表示没有下一个邻接点了}void atriculation_point_step2 (int v) {int min;int w = -1;visited[v] = ++count;min = visited[v];while (-1 != (w = next_adjacent_vertex(v,w+1))) {if (0 == visited[w]) {atriculation_point_step2 (w);if (low[w] >= visited[v]) {printf ("-->%c\n",97+v);}if (min > low[w]) {min = low[w];}}else if(visited[w] < min){min = visited[w];//w已经被访问过,w是v在生成树上的祖先}}low[v] = min;}void atriculation_point_step1 (int v) {int adjacent = next_adjacent_vertex (v,0);memset (visited,0,sizeof(visited));visited[v] = ++count;atriculation_point_step2(adjacent);if (count < vertex_num) {printf ("-->%c\n",97+v);while (-1!= (adjacent = next_adjacent_vertex(v,adjacent+1))) {if (0 == visited[adjacent]) {    atriculation_point_step2(adjacent);}}}}int main () {atriculation_point_step1 (0);printf ("%d\n",count);return 0;}