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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

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

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

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

?

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

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

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

?

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

?

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

最小點覆蓋=最大匹配數(shù)

  額,現(xiàn)在還沒想到如何證明……

一、匈牙利算法

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

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

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

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

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

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

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

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

?? ????? 2.???P經(jīng)過取反操作(即非M中的邊變?yōu)?span style="line-height:21px;">M中的邊,原來M中的邊去掉)可以得到一個更大的匹配M’。

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

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

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

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

?? ????? (3)重復(fù)(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算法:

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

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

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

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

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

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

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

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

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

復(fù)雜度分析:由于在不擴大匹配的情況下每次匈牙利樹做如上調(diào)整之后至少增加一個元素,因此最多執(zhí)行n次就可以找到一條增廣路,最多需要找n條增廣路,故最多執(zhí)行n^2次修改頂標(biāo)的操作,而每次修改頂標(biāo)需要掃描所有弧,這樣修改頂標(biāo)的復(fù)雜度就是O(n^2)的,總的復(fù)雜度是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,由于生長匈牙利樹的時候每條弧的頂標(biāo)增量相同,因此修改每個slack需要常數(shù)時間(注意在修改頂標(biāo)后和把已蓋Y節(jié)點對應(yīng)的X節(jié)點加入匈牙利樹的時候是需要修改slack的)。這樣修改所有slack值時間是O(n)的,每次增廣后最多修改n次頂標(biāo),那么修改頂標(biāo)的總時間降為O(n^2)n次增廣的總時間復(fù)雜度降為O(n^3)。事實上這樣實現(xiàn)之后對于大部分的數(shù)據(jù)可以比O(n^4)的算法快一倍左右。

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

另一種說法:

KM算法(轉(zhuǎn))

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

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

?

轉(zhuǎn)載于:https://www.cnblogs.com/TenderRun/p/5321381.html

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。