关节点:可以将一个连通分量分割成两个或多个连通分量的点。
重连通图:没有关节点的图,在重连通图中任意两点之间至少存在两条路径
关节点求法:算法较难理解,算法结合了先序深度搜索和后序深度搜索,先序深度搜索确定每个点访问的顺序,而后序深度搜索则根据先序计算的顺序确定关节点。具体递归算法步骤:
递归算法: 递归算法中,第一部分为记录结点访问次序,中间部分为调用递归函数访问子节点,第三部分为根据递归函数的退出,来确定结点的回边。
1.从vi开始,调用递归算法
2.一直递归到某个点s(该没有未被访问的邻接点),这个点有两种状况,第一种是没有回边,只有一条指向双亲的边,则记录该结点的回边值为该结点的双亲的访问顺序值,第二种是有回边,则记录该点回边值为指向最先访问的祖先的访问顺序值,退出递归函数
3.从第二步退出递归函数后,如果s结点为无回边状况,则判断s的父节点为关节点,如果为有回边状况,则s结点的回边值肯定小于双亲的访问顺序值,则将双亲的回边值也更新为该值。
4.重复2,3步骤。
代码实现:
/*** @name 得到关节点* @use 获得图的关节点,图用矩阵(二维数组)表示* @param chart* @param start 起始结点* @return points*/public static function getKeyPoint($chart, $start = 0) {$points = array($start);//已访问的结点$visited = array($start => 1);//各节点的访问顺序$low = array();//各节点的回边值$count = 1;$T = array();//保存关节点$temp = true;foreach ($chart[$start] as $key => $value) {if ($value !== 0 && !in_array($key, $points)) {self::getKeyPointDFS($chart, $key, $points, $visited, $low, $count, $T);if ($count < count($chart) && $temp) {$T[] = $start;$temp = false;}}}return $T;}public static function getKeyPointDFS($chart, $start, &$points,&$visited, &$low, &$count, &$T) {$points[] = $start;$visited[$start] = $min = ++$count;foreach ($chart[$start] as $key => $value) {if ($value == 0) {continue;}if (!in_array($key, $points)) {self::getKeyPointDFS($chart, $key, $points, $visited, $low, $count, $T);if ($low[$key] < $min) $min = $low[$key];if ($low[$key] >= $visited[$start]) $T[] = $start;} else if($visited[$key] < $min) {$min = $visited[$key];}}$low[$start] = $min;}