日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

图论:关于二分图的总结(转载)

發布時間:2023/11/27 生活经验 63 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图论:关于二分图的总结(转载) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

二分圖是這樣一個圖,它的頂點可以分類兩個集合XY,所有的邊關聯在兩個頂點中,恰好一個屬于集合X,另一個屬于集合Y。

?

  最大匹配:圖中包含邊數最多的匹配稱為圖的最大匹配。

  完美匹配:如果所有點都在匹配邊上,稱這個最大匹配是完美匹配。

  最小覆蓋:最小覆蓋要求用最少的點(X集合或Y集合的都行)讓每條邊都至少和其中一個點關聯。

?

  最小路徑覆蓋:用盡量少的不相交簡單路徑覆蓋有向無環圖G的所有結點。解決此類問題可以建立一個二分圖模型。把所有頂點i拆成兩個:X結點集中的iY結點集中的i',如果有邊i->j,則在二分圖中引入邊i->j',設二分圖最大匹配為m,則結果就是n-m

?

  最大獨立集問題: 在N個點的圖G中選出m個點,使這m個點兩兩之間沒有邊.求m最大值.如果圖G滿足二分圖條件,則可以用二分圖匹配來做.最大獨立集點數?=?N?-?最大匹配數

最小點覆蓋=最大匹配數

  額,現在還沒想到如何證明……

一、匈牙利算法

G=(V,{R})是一個無向圖。如頂點集V可分割為兩個互不相交的子集,并且圖中每條邊依附的兩個頂點都分屬兩個不同的子集。則稱圖G為二分圖。

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

?? ????? 選擇這樣的邊數最大的子集稱為圖的最大匹配問題(maximal?matching?problem)?

? ? ???? 如果一個匹配中,圖中的每個頂點都和圖中某條邊相關聯,則稱此匹配為完全匹配,也稱作完備匹配。

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

匈牙利算法是求解最大匹配的有效算法,該算法用到了增廣路的定義(也稱增廣軌或交錯軌):若P是圖G中一條連通兩個未匹配頂點的路徑,并且屬M的邊和不屬M的邊(即已匹配和待匹配的邊)P上交替出現,則稱P為相對于M的一條增廣路徑。

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

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

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

?? ????? 3.???MG的最大匹配當且僅當不存在相對于M的增廣路徑。

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

?? ????? (1)M為空

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

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

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int maxn=110;
 6 int n,m,a,b,ans,cnt,fir[maxn],nxt[maxn],to[maxn],mat[maxn];
 7 bool vis[maxn];
 8 void addedge(int a,int b){
 9     nxt[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;
10 }
11 bool Solve(int node){
12     vis[node]=true;
13     for(int i=fir[node];i;i=nxt[i]){
14         if(mat[to[i]]&&(vis[mat[to[i]]]||!Solve(mat[to[i]])))continue;
15         mat[to[i]]=node;
16         return true;
17     }
18     return false;
19 }
20 int main(){
21     freopen("flyer.in","r",stdin);
22     freopen("flyer.out","w",stdout);
23     scanf("%d%d",&n,&m);
24     while(scanf("%d%d",&a,&b)!=EOF)
25         addedge(a,b);
26     for(int i=1;i<=n-m;i++){
27         memset(vis,0,sizeof(vis));
28         if(Solve(i))
29             ans++;
30     }
31     printf("%d\n",ans);
32     return 0;
33 }

  題目是”飛行員匹配“。

?

二、KM算法:

二分圖最優匹配:對于二分圖的每條邊都有一個權(非負),要求一種完備匹配方案,使得所有匹配邊的權和最大,記做最優完備匹配。(特殊的,當所有邊的權為1時,就是最大完備匹配問題)

解二分圖最優匹配問題可用窮舉的方法,但窮舉的效率=n!,所以我們需要更加優秀的算法。

先說一個定理:設M是一個帶權完全二分圖G的一個完備匹配,給每個頂點一個可行頂標(ix頂點的可行標用lx[i]表示,第jy頂點的可行標用ly[j]表示),如果對所有的邊(i,j)?in?G,都有lx[i]+ly[j]>=w[i,j]成立(w[i,j]表示邊的權),且對所有的邊(i,j)?in?M,都有lx[i]+ly[j]=w[i,j]成立,則M是圖G的一個最優匹配。

KuhnMunkras算法(即KM算法)流程:

?? ????? (1)初始化可行頂標的值

?? ????? (2)用匈牙利算法尋找完備匹配

?? ????? (3)若未找到完備匹配則修改可行頂標的值

?? ????? (4)重復(2)(3)直到找到相等子圖的完備匹配為止

KM算法主要就是控制怎樣修改可行頂標的策略使得最終可以達到一個完美匹配,首先任意設置可行頂標(如每個X節點的可行頂標設為它出發的所有弧的最大權,Y節點的可行頂標設為0),然后在相等子圖中尋找增廣路,找到增廣路就沿著增廣路增廣。而如果沒有找到增廣路呢,那么就考慮所有現在在匈牙利樹中的X節點(記為S集合),所有現在在匈牙利樹中的Y節點(記為T集合),考察所有一段在S集合,一段在not?T集合中的弧,取???????delta?=?min?{l(xi)+l(yj)-w(xi,yj)?,?|?xi?in?S,?yj???in?not?T}????。明顯的,當我們把所有S集合中的l(xi)減少delta之后,一定會有至少一條屬于(S,?not?T)的邊進入相等子圖,進而可以繼續擴展匈牙利樹,為了保證原來屬于(S,T?)的邊不退出相等子圖,把所有在T集合中的點的可行頂標增加delta。隨后匈牙利樹繼續擴展,如果新加入匈牙利樹的Y節點是未蓋點,那么找到增廣路,否則把該節點的對應的X匹配點加入匈牙利樹繼續嘗試增廣。

復雜度分析:由于在不擴大匹配的情況下每次匈牙利樹做如上調整之后至少增加一個元素,因此最多執行n次就可以找到一條增廣路,最多需要找n條增廣路,故最多執行n^2次修改頂標的操作,而每次修改頂標需要掃描所有弧,這樣修改頂標的復雜度就是O(n^2)的,總的復雜度是O(n^4)的。

?????對于not?T的每個元素yj,定義松弛變量slack(yj)?=min{l(xi)+l(yj)-w(xi,yj),?|?xi?in?S},很明顯每次的delta?=?min{slack(yj),?|?yj???in?not?T},每次增廣之后用O(n^2)的時間計算所有點的初始slack,由于生長匈牙利樹的時候每條弧的頂標增量相同,因此修改每個slack需要常數時間(注意在修改頂標后和把已蓋Y節點對應的X節點加入匈牙利樹的時候是需要修改slack的)。這樣修改所有slack值時間是O(n)的,每次增廣后最多修改n次頂標,那么修改頂標的總時間降為O(n^2)n次增廣的總時間復雜度降為O(n^3)。事實上這樣實現之后對于大部分的數據可以比O(n^4)的算法快一倍左右。

利用二分圖匹配的匈牙利算法和KM算法,我們可以求解大部分的關于二分圖的問題,它們提供了求解最大匹配和最優匹配的有效算法,在具體編程時我們只要多注意優化,我們就可以得出求解這類問題的有效方法,從而可以對這類實際問題進行有效合理的解決。

另一種說法:

KM算法(轉)

??? ? ? KM算法是通過給每個頂點一個標號(叫做頂標)來把求最大權匹配的問題轉化為求完備匹配的問題的。設頂點Xi的頂標為A[i],頂點Yi的頂標為B?[i],頂點XiYj之間的邊權為w[i,j]。在算法執行過程中的任一時刻,對于任一條邊(i,j)A[i]+B[j]>=w[i,j]始終?成立。KM算法的正確性基于以下定理:
?  若由二分圖中所有滿足A[i]+B[j]=w[i,j]的邊(i,j)構成的子圖(稱做相等子圖)有完備匹配,那么這個完備匹配就是二分圖的最大權匹配。
   這個定理是顯然的。因為對于二分圖的任意一個匹配,如果它包含于相等子圖,那么它的邊權和等于所有頂點的頂標和;如果它有的邊不包含于相等子圖,那么它的邊權和小于所有頂點的頂標和。所以相等子圖的完備匹配一定是二分圖的最大權匹配。
?  初始時為了使A[i]+B[j]>=w[i,j]恒成立,令A[i]為所有與頂點Xi關聯的邊的最大權,B[j]=0。如果當前的相等子圖沒有完備匹配,就按下面的方法修改頂標以使擴大相等子圖,直到相等子圖具有完備匹配為止。
?  我們求當前相等子圖的完備匹配失敗了,是因為對于某個X頂點,我們找不到一條從它出發的交錯路。這時我們獲得了一棵交錯樹,它的葉子結點全部是X頂點。現在我們把交錯樹中X頂點的頂標全都減小某個值dY頂點的頂標全都增加同一個值d,那么我們會發現:
?兩端都在交錯樹中的邊(i,j)A[i]+B[j]的值沒有變化。也就是說,它原來屬于相等子圖,現在仍屬于相等子圖。
?兩端都不在交錯樹中的邊(i,j)A[i]B[j]都沒有變化。也就是說,它原來屬于(或不屬于)相等子圖,現在仍屬于(或不屬于)相等子圖。
?X端不在交錯樹中,Y端在交錯樹中的邊(i,j),它的A[i]+B[j]的值有所增大。它原來不屬于相等子圖,現在仍不屬于相等子圖。
?X端在交錯樹中,Y端不在交錯樹中的邊(i,j),它的A[i]+B[j]的值有所減小。也就說,它原來不屬于相等子圖,現在可能進入了相等子圖,因而使相等子圖得到了擴大。
?  現在的問題就是求d值了。為了使A[i]+B[j]>=w[i,j]始終成立,且至少有一條邊進入相等子圖,d應該等于min{A[i]+B[j]-w[i,j]|Xi在交錯樹中,Yi不在交錯樹中}
?  以上就是KM算法的基本思路。但是樸素的實現方法,時間復雜度為O(n4)——需要找O(n)次增廣路,每次增廣最多需要修改O(n)次頂?標,每次修改頂標時由于要枚舉邊來求d值,復雜度為O(n2)。實際上KM算法的復雜度是可以做到O(n3)的。我們給每個Y頂點一個松弛量函數?slack,每次開始找增廣路時初始化為無窮大。在尋找增廣路的過程中,檢查邊(i,j)時,如果它不在相等子圖中,則讓slack[j]變成原值與A?[i]+B[j]-w[i,j]的較小值。這樣,在修改頂標時,取所有不在交錯樹中的Y頂點的slack值中的最小值作為d值即可。但還要注意一點:修改?頂標后,要把所有的slack值都減去d

原文:http://www.360doc.com/content/11/0718/14/3701281_134273282.shtml

?

轉載于:https://www.cnblogs.com/TenderRun/p/5321381.html

總結

以上是生活随笔為你收集整理的图论:关于二分图的总结(转载)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。