二分圖簡介


二分圖又稱作二部圖,是圖論中的一種特殊模型。 設G=(V,E)是一個無向圖,如果頂點V可分割為兩個互不相交的子集(A,B),並且圖中的每條邊(i,j)所關聯的兩個頂點i和j分別屬於這兩個不同的頂點集(i in A,j in B),則稱圖G為一個二分圖。

 

 



 

簡而言之,就是頂點集V可分割為兩個互不相交的子集,並且圖中每條邊依附的兩個頂點都分屬於這兩個互不相交的子集

無向圖G為二分圖的充分必要條件是,G至少有兩個頂點,且其所有回路的長度均為偶數

 

給定一個二分圖G,在G的一個子圖M中,M的邊集中的任意兩條邊都不依附於同一個頂點,則稱M是一個匹配。

選擇這樣的邊數最大的子集稱為圖的最大匹配問題(maximal matching problem)
如果一個匹配中,圖中的每個頂點都和圖中某條邊相關聯,則稱此匹配為完全匹配,也稱作完備匹配.
 
二分圖的最大匹配有許多實際的應用。例如 ,把一個機器集合L和要同時執行的任務集合R相匹配,E中有邊(u,v),就說明一台特定
機器u(屬於L)能夠完成一項特定任務v(屬於R),最大匹配可以為盡可能多的機器提供任務

最大匹配在實際中有廣泛的用處,求最大匹配的一種顯而易見的算法是:先找出全部匹配,然后保留匹配數最多的。即回溯法,但是這個算法的復雜度為邊數的指數級函數。因此,需要尋求一種更加高效的算法。

   二分圖的最大匹配有2種實現,網絡流和匈牙利算法。(《算法導論》第26章有講網絡流算法)

求最大匹配的一種顯而易見的算法是:先找出全部匹配,然后保留匹配數最多的.但是這個算法的復雜度為邊數的指數級函數.因此,需要尋求一種更加高效的算法.

匈牙利算法是求解最大匹配的有效算法,該算法用到了增廣路的定義(也稱增廣軌或交錯軌):若邊集合P是圖G中一條連通兩個未匹配頂點的路徑,並且屬M的邊和不屬M的邊(即已匹配和待匹配的邊)在P上交替出現,則稱P為相對於M的一條增廣路徑。((舉例來說,有A、B集合,增廣路由A中一個點通向B中一個點,再由B中這個點通向A中一個點……交替進行)。

由增廣路徑的定義可以推出下述三個結論:

    1.  P的路徑長度必定為奇數,第一條邊和最后一條邊都不屬於M。

    2.  P經過“取反操作”(即非M中的邊變為M中的邊,原來M中的邊去掉)可以得到一個更大的匹配M’。

(我畫的例子:

 

路徑A-F為路徑P,BC和DE屬於M,可以看到在路徑p上屬於M和邊和不屬於M的邊交替出現。先黑后紅,再黑,在紅。

由於增廣路規定是連同2個未匹配的頂點。所有P的長度一定是奇數。

 P經過“取反操作”(即非M中的邊變為M中的邊,原來M中的邊去掉)可以得到一個更大的匹配M’。可以從圖中看出來,

把原來匹配的邊(紅色表示)去掉,把黑色的邊加上,匹配數由2變成了3.增大了。(大概增廣路徑的名字也是這么來的吧!)

 

3.  M為G的最大匹配當且僅當不存在相對於M的增廣路徑。

百度百科增廣路:http://baike.baidu.com/view/3585026.htm

從而可以得到求解最大匹配的匈牙利算法:

(1)置M為空

(2)找出一條增廣路徑P通過“取反操作”獲得更大的匹配M’代替M

(3)重復(2)操作直到找不出增廣路徑為止

根據該算法,可以選擇深搜或者廣搜實現,下面給出易於實現的深度優先搜索(DFS)實現。

//prototype


int    n, m, match[100];                        //二分圖的兩個集合分別含有n和m個元素,match[i]存儲集合m中的節點i在集合n中的匹配節點,初值為-1。
bool    visited[100], map[100][100];                 //map存儲鄰接矩陣。


bool DFS(cosnt int &k)
{
      for(int i = 0; i < m; i++)
           if( map[k][i] && !visited[i]    )

          {

               visited[i] = true;
             if( match[i] == -1 || DFS(match[i]) )   //尋找是否為增廣路徑

         {

           match[i] = k;            //路徑取反操作。

           return true;

              }
          }
       return false;
}

 

int main(void)
{
//...........

       int     count = 0;

       memset(match, -1, sizeof(match));
       for(i = 0; i < n; i++)

      {    //以二分集中的較小集為n進行匹配較優
             memset(visited, 0,sizeof(visited));
            if( DFS(i) )     ++count;    //count為匹配數
       }
//............
return 0;
}

優點:實現簡潔,容易理解,適用於邊比較多的圖,DFS找增廣路快.

相比較而言,廣度優先搜索的優點:適用於稀疏二分圖,邊較少,增廣路較短。(BFS實現略)

 

         另外,二分圖最大匹配可以轉換成最大流問題來解。假設二分圖的兩個頂點集分別為X, Y,那么我們在圖中添加一個源s,和一個匯t。同時,在s與X的每個頂點間加一條有向邊(s, vx),在Y的每個頂點與t間加一條有向邊(vy, t)。X與Y的每條邊也變為X->Y的有向邊。圖中每條邊的容量為1。則最大匹配問題就轉換為求轉換后的圖G'的最大流的問題。利用Ford-Fulkerson方法求最大流,時間復雜度為O(VE), V為頂點數,E為邊數。具體證明參考《算法導論》。但是,經典的求二分圖最大匹配的算法是Edmond於1965年提出的匈牙利算法。


題目:

JOJ 1102    Courses http://acm.jlu.edu.cn/joj/showproblem.php?pid=1102   (最基本的二分圖匹配)

JOJ   2393   The problem of a CEO  http://acm.jlu.edu.cn/joj/showproblem.php?pid=2393(二分圖匹配+字符串處理)


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/Fandywang_jlu/archive/2008/03/20/2201351.aspx

熟悉的陌生人分析

原題

大家都知道facebook用戶都是雙向的好友,a是b的好友,那么b一定是a的好友,現在給定一個用戶列表,其中有些用戶是好友,有些不是,請判斷,這些用戶是否可以划分為兩組,並且每組內的用戶,互相都不是好友。如果能,請給出這個划分。

例子1: 用戶:{1, 2, 3} 好友關系:1-2, 2-3 划分:{1,3} {2}

例子2: 用戶{1,2,3,4} 好友關系:1-2, 2-3, 3-4,4-1 划分:{1, 3}{2, 4}

分析

有很多面試題比較直接,看到題目,面試者很自然的就想到用什么方法,這時候,往往面試官要的是bug-free的code;還有一些問題,不那么直接,那就是考察,應試者的分析問題、分解問題的能力。往往是一個相對復雜的問題,分解為我們見過的、相對簡單的問題;還有一類問題,從實際當中來,這就需要有建模的能力,也可以說是把問題抽象出來的能力,然后才是分解成小的問題等。這樣的題目,能夠全面的考察應試者的能力。例如今天的面試題。

今天的面試題來自facebook的實際問題。像在我們國內,有很多同學在做新浪微博的數據挖掘,好友推薦、關系預測、圈子發現、轉發分析、影響力分析等等,這些都是很實際、很有用的問題,每一個問題,都可以作為一個值得深入探討的面試題。

相對而言,今天的面試題目比較簡單。因為建模的部分,已經在題目中給出了。稍想一下,圖分割的問題。facebook的好友關系是雙向的,意味着是無向圖(新浪微博,twitter都是有向圖)。然后,要把圖划分為兩組,這兩組滿足什么條件呢?組內沒有邊,組間有邊。這顯然就是一個二分圖。

那問題很明顯了,就是facebook好友關系構成的圖,是否是一個二分圖?如果是,請找到這個划分。就是二分圖判斷+找到一個划分即可。

根據二分圖的特性,一條邊上的兩個點,肯定是屬於不同的組。如果它們出現在同一個組中,肯定就不是二分圖了。怎么判斷,一條邊上的兩個點,分屬於不同的組呢?我們需要遍歷圖,如果找到一條邊,兩個節點,都在同一組,則不是二分圖;如果圖遍歷完成之后,沒有找到這樣的邊,則是二分圖。我們在遍歷的過程中,我們需要區分,一條邊的兩個節點分屬於不同的組,這里我們用到了染色法。核心思想如下:

從某一個點開始,將這個節點染色為白色,並且開始廣度優先遍歷,找到與其相鄰的節點,如果是二分圖,相鄰節點的顏色都應該不同。如果是黑色,則不變;如果是無色,則染成黑色;如果是白色,也就是同色,程序退出。當圖遍歷完畢時,沒有相鄰節點同色的,則是二分圖,標記為白色和黑色的兩組就是一個划分。

來看兩個例子,第一個圖中的例子2:

步驟 遍歷節點 相鄰節點 隊列
1 1:白 2:黑,4:黑 2,4
2 2:黑 1:白,3:白 4,3
3 4:黑 1:白,3:白 3
4 3:白 2:黑,4:黑

隊列空,結束遍歷。找到划分{1,3}白{2,4}黑。

再看一個不是二分圖的例子: 用戶{1,2,3,4} 關系:1-2,1-3,1-4,2-3,3-4.

判斷步驟如下:

步驟 遍歷節點 相鄰節點 隊列
1 1:白 2:黑,3:黑,4:黑 2,3,4
2 2:黑 1:白,3:白 3,4
 

發現3矛盾了,則上面的關系,不夠成二分圖。

【分析完畢】

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM