点连通度与边连通度的求解

原博客地址:连通度

回到正题,首先介绍下什么是图的边连通度和点连通度。一般来说,点连通度是指对应一个图G,对于所有点集U属于V(G),也就是V(G)的子集中,使得G-U要么是一个非连通图,要么就是一个平凡图(即仅包含一个独立点的图),其中最小的集合U的大小就是图G的点连通度,有时候也直接称为图的连通度。通俗点说,就是一个图G最少要去掉多少个点会变成非连通图或者平凡图。当然对于一个完全图来说Kn来说,它的连通度就是n-1。

同理,边连通度就是对于一个非平凡图G,至少去掉多少条边才能使得该图变成非连通图。我们的问题就是,对于任意一个图,如何求该图的连通度以及边连通度?这跟最大流问题有什么联系?

简单起见,我们先说如何求一个图的边连通度lamda(G)。(基于无向图考虑)

对于图G,设u,v是图G上的两个顶点,定义r(u,v)为删除最少的边,使得u到v之间没有通路。将图G转换成一个流网络H,u为源点,v是汇点,边容量均为1,那么显然r(u,v)就是流网络的最小割,根据(二)里的介绍,其等于流网络的最大流。

但是,目前为止我们还没解决完问题,因为显然我们要求的边连通度lamda(G)是所有的点对对应的r(u,v)中最小的那个值。这样的话我们就必须遍历所有的点对,遍历的的复杂度为O(n*n)。这显然代价太高,而事实上,我们也不必遍历所有点对。

点连通度与边连通度的求解_第1张图片

如图所示,设S为图G的最小割集,那么lamda(G)=|S|。设在取任意一个点u,若u在L内,那么必然至少存在一个点v,使得r(u,v)=|S|(v是在R内时即成立)。所以,我们只需要任取一个点u,计算u和其他点的r(u,v),取最小者,必然是等于最小割集,即边连通度。

[java]  view plain copy
  1. public class EdgeConnectivity {  
  2.   
  3.     /** 
  4.      * @param args 
  5.      */  
  6.     public static void main(String[] args) {  
  7.         double graph[][]={{0,1,0,1,0,0},  
  8.                   {1,0,1,0,1,0},  
  9.                   {0,1,0,0,0,1},  
  10.                   {1,0,0,0,1,0},  
  11.                   {0,1,0,1,0,1},  
  12.                   {0,0,1,0,1,0}};  
  13.         double graph2[][]={  
  14.                   {0,1,1,1,1,1},  
  15.                   {1,0,1,1,1,1},  
  16.                   {1,1,0,1,1,1},  
  17.                   {1,1,1,0,1,1},  
  18.                   {1,1,1,1,0,1},  
  19.                   {1,1,1,1,1,0}};  
  20.         System.out.println(edgeConnectivity(graph2));  
  21.   
  22.     }  
  23.       
  24.       
  25.     public static int edgeConnectivity(double graph[][])  
  26.     {  
  27.         double min=Double.MAX_VALUE;  
  28.         for(int i=1;i
  29.         {  
  30.             double maxflow=FordFulkerson.edmondsKarpMaxFlow(graph, 0, i);  
  31.             if(maxflow
  32.                 min=maxflow;  
  33.         }  
  34.         return (int)min;  
  35.     }  
  36.   
  37. }  

对于点连通度来说,可能就要复杂点了。求点连通度的方法就是转换为求边连通度,所以就需要我们巧妙的去构造一个流网络,使得其边连通度等于我们原来的图的点连通度。构造流网络N:

若G为无向图:

(1) 原 G 图中的每个顶点 v 变成 N 网中的两个顶点 v' 和 v" ,顶点 v' 至 v" 有一条弧(有向边)连接,弧容量为 1;
(2) 原 G 图中的每条边 e = uv ,在 N 网中有两条弧 e’= u"v',e"=v"u' 与之对应, e' 弧容量为 ∞ , e" 弧容量为 ∞
(3) 求该网络的边连通度

若 G 为有向图:
(1) 原 G 图中的每个顶点变成 N 网中的两个顶点 v’ 和 v” ,顶点 v' 至 v” 有一条弧连接,弧容量为 1
(2) 原 G 图中的每条弧 e = uv 变成一条有向轨 u'u"v'v" ,其中轨上的弧 u"v' 的容量为 ∞;

如下图所示,原图G:

点连通度与边连通度的求解_第2张图片

转换后的流网络N:

点连通度与边连通度的求解_第3张图片


Ok,如何在流网络N上求边连通度呢?按照我们求边连通度的做法,选定一个点u作为源点,然后遍历点对,其中v!=u。但是在这里源点的选择必须是u‘’,也就是说必须是拆分后的后点,也就是两个撇的点。汇点的遍历只能是前点,也就是一个撇的点。为什么呢?很简单,比如若u’为源点,那么最大流只能是1,因为只有一条有向边从u‘连接到u’‘,切其容量为1。同理,若v‘’为汇点,那么最大流也只能是1,因为只有(v’,v'')的有向边指向v‘’,且容量为1。

这样,我们也就更容易理解为什么是采用上面的策略来转换到流网络N了吧。代码就不上了,和求边连通度很类似。

*****************************************************************************************************************************************************************************************

上面的图很漂亮,转过来学习学习!

以下是个人观点:

边连通度还是较好理解的,最小割对应了最少需要删除的边数。因为是删边,我们求得最小割无非是将顶点分成两个集合是S,T,那么我们任取一点u,必然属于两个集合之中的一个,不管是S还是T,因为是无向图,s到t的最大流必然等于t到s的最大流,因此我们可以任取一点作为源点,然后暴力枚举汇点,求最大流

至于点连通度不那么直观,首先我们考虑完全图,可以发现源点到枚举的任意汇点都有直达边,边权为inf,因此完全图对应的最小割是inf;

不是完全图,原图中必然存在u,v没有边,我们选择u为源点,v为汇点,求最小割,那么最小割中的边在原图对应的点就是我们要求的割点集,删除这些点u,v就不连通了,因此这里要暴力枚举u,v;注意必须两两枚举,因为如果任取一个作为源点,那么如果取的刚好是割点集的点,那就麻烦了,源点是不会有流入的,因此按照最大流算法求出来的源点不在割点集,就会出错。区别是很明显的,求割边不删点,而求割点需要删点,因此后者需要暴力枚举源汇点。

你可能感兴趣的:(图的连通性)