现在的位置: 首页 > 综合 > 正文

无向图求点割集算法

2012年10月27日 ⁄ 综合 ⁄ 共 2130字 ⁄ 字号 评论关闭

 

黑书上给出了关于求点割集的算法,但是比较模糊,我查阅了网络上的相关资料,理解了求点割集的过程,写出如下求点割集的代码,并写了一些简单的证明.

 

割点集的定义:如果在连通图G中去掉某一点后图不连通,那么这个点即为G的割点,所有割点的集合即为点割集。

 

求点割集的方法:利用tarjan算法的思想,用数组dfn[v]存储DFS遍历到点v的时间,数组low[v]存储点v能追溯到最早的祖先节点。

如果对于点v来说有如下结论:

 

 

1.如果点v是DFS序列的根节点,则如果v有一个以上的孩子,则v是一个割点。

2.如果v不是DFS序列根节点,并且点v的任意后继u能追溯到最早的祖先节点low[u]>=dfn[v],则v是一个割点。

 

 

证明1:

  

       假设DFS遍历的第一个节点v不是割点,那么则有low[v]=dfn[v]=1,继续对v的孩子节点u遍历,必然有low[u]>=dfn[v],按照第二条性质,则v是割点,但我们已经假设v不是割点。这是由于v是DFS遍历的起始节点,在遍历序列中v没有祖先节点,v的所有后继节点能追溯到最早的祖先节点最多也就是v了,不可能比v再早了,因此必须把DFS遍历的第一个节点v单独考虑,那么怎么判断v是不是割点呢?

      例如上图,设v是DFS序列访问的第一个节点,对v的孩子节点u和u的所有孩子节点进行DFS遍历并标记为已经访问后,如果v的另一个孩子节点k没有被标记为已经访问,那么u和k之间一定不存在边,也就是说u和k之间的连通必然需要点v,因此如果v是DFS遍历的第一个节点,对v是否为割点的判断方法是:看v是不是有多个孩子,如果有则v是割点。

证明2:

      如果v不是DFS遍历的第一个节点,那么对于v的所有后继节点来说,如果v不是割点(也就是如果删掉点v,剩下的图还是连通图),那么v的后继节点必然能追溯到DFS遍历序列中v的祖先节点,也就是v的后继节点中存在到达DFS序列中v的祖先的路径,因此当DFS回溯到v节点时对于v的所有后继节点u来说,都有low[u]<dfn[v]。

      如果v是一个割点,对所有v的后继节点u进行DFS后,必然有low[u]>=dfn[v],这是因为,当遍历v并将其锁定后,到达v的祖先节点的路径已经被封死,v的后继节点必然不可能访问到v的祖先节点,因此,必然有low[u]>=dfn[v]。

 

 

有了上面的分析,下面写出求无向图点割集的代码:

 

 

抱歉!评论已关闭.