World Final

God Medal
重连通分量 (Biconnected Component)

重连通分量 (Biconnected Component)

 

     在无向连通图G中,当且仅当删去G中的顶点 v及所有依附于v的所有边后,可将图分割成两个或两个以上的连通分量,则称顶点v为关节点。

     没有关节点的连通图叫做重连通图。在重连通图上, 任何一对顶点之间至少存在有两条路径, 在删去某个顶点及与该顶点相关联的边时, 也不破坏图的连通性。

一个连通图G如果不是重连通图,那么它可以包括几个重连通分量。在一个无向连通图G中, 重连通分量可以利用深度优先生成树找到。

 

 算法介绍:

     dfn 顶点的深度优先数,标明进行深度优先搜索时各顶点访问的次序。如果在深度优先生成树中,顶点 u 是顶点 v 的祖先, 则有dfn[u]<dfn[v] 。

深度优先生成树的根是关节点的充要条件是它至少有两个子女。

其它顶点 u 是关节点的充要条件是它至少有一个子女 w, 从 w 出发, 不能通过 w、w 的子孙及一条回边所组成的路径到达 u 的祖先。

在图G的每一个顶点上定义一个low值,low[u]是从u或u的子孙出发通过回边可以到达的最低深度优先数。

low[u] = min{ dfn[u],
min{ low[w] | w 是 u 的一个子女 },
min{ dfn[x] | (u, x) 是一条回边 } }

u 是关节点的充要条件是:
u 是具有两个以上子女的生成树的根
u 不是根,但它有一个子女 w,使得
low[w]≥ dfn[u]

这时 w 及其子孙不存在指向顶点u的祖先的回边。

计算dfn与low的算法 (1)

 

Code

计算dfn与low的算法 (2)

 

Code

 

在算法DfnLow增加一些语句, 可把连通图的边划分到各重连通分量中。
首先, 根据 DfnLow (w, u)的返回, 计算low[w]。
如果low[w]>=dfn[u],则开始计算新的重连通分量。
在算法中利用一个栈, 在遇到一条边时保存它。
可在函数Biconnected中就能输出一个重连通分量的所有的边。

当 n > 1 时输出重连通分量(1)

 

Code

 

当 n > 1 时输出重连通分量(2)

void Graph::Biconnected ( const int u, const int v ) {
//私有函数:计算dfn与low, 根据其重连通分量输出Graph的边。
//在产生的生成树中, v 是 u 的双亲结点, S 是一个初始为空的栈,
//应声明为图的数据成员。

Code

 

算法 Biconnected 的时间代价是 O(n+e)。其中 n 是该连通图的顶点数,e 是该连通图的边数。
此算法的前提条件是连通图中至少有两个顶点,因为正好有一个顶点的图连一条边也没有。

 

Practice

PKU 3177

 

January 2006 Problem 'rpaths' Analysis
                                             by Bruce Merry

The problem can be restated as requiring that one adds the minimum number of edges to make the graph biconnected. The first step is to identify the existing biconnected components; refer to your favourite algorithms textbook to see what a biconnected component is and how to identify one; be aware though that there are two variants of bi-connectivity, depending on whether separate routes must be vertex-disjoint or edge-disjoint; in this case they must be edge-disjoint, so biconnected components are separated by articulation edges (vertex-disjoint biconnectivity is more common and probably what your favourite textbook will discuss, but the algorithms involved are very similar).

We will never need to add edges within a biconnected component, so for the purposes of the problem we can collapse each biconnected component to a single vertex. This will leave the graph as a tree. Each leaf will need a new edge added (since there is currently only one road to its parent), so at least ceil(leaves / 2) edges must be added. It is also possible to show that this number is sufficient (hint: joining the left-most and right-most leaf and re-collapsing the newly created biconnected component will almost always reduce the number of leaves by 2). So it is sufficient to count the leaves; you don't actually need to work out which new paths to add.

 

Code

posted on 2008-07-30 23:18  BLess  阅读(6520)  评论(4编辑  收藏  举报