二分圖匹配相關概念及內容

這裏的概念比較多容易混淆,而且出題時這種可能會針對這些內容直接出結論題,整理一下

  • 二分圖的概念

如果一個圖可以將其頂點分成兩個互不相交的子集,且圖中的每條邊所連的兩個點分屬這兩個子集,那麼這個圖可以稱作二分圖。
一個無向圖GG爲二分圖的充要條件是,GG至少有兩個頂點,且其所有迴路的長度均爲偶數。所以說判斷奇環也就是判斷二分圖。二分圖的判斷可以用二分圖染色,就是使左邊的點集是一個顏色右邊的點集是一個顏色,dfsdfsbfsbfs都可以實現。

  • 二分圖最大匹配

二分圖匹配就是求出一個原圖的子圖使得任意兩條邊不連在同一個頂點上。
最大匹配就是一個使得子圖邊數最多的匹配。

匈牙利算法是在二分圖問題中很常用的一種算法,作用就是來求最大匹配。
主要流程如下:
枚舉左側的點AA看這個點是否有連向右側的邊,如果有並且連向的這個點BB沒有被匹配,那麼標記這兩個點匹配成功;如果右側有邊的點BB已經被匹配了,那就“協商”,讓這個匹配右側點BB的左側點CC再去匹配另一個右側點DD,看是不是能給當前點AA空出位置來,如果可以那麼就讓CC去匹配DDAA來匹配BB,思想就是如此。

可以發現已經匹配的點不會在接下來的算法流程中失配,最多隻會更換匹配的對象。
算法中首先需要遍歷每個點,然後再讓每個點找連向右側的邊,複雜度Θ(nm)\Theta(nm)
由於經常會遍歷到沒有匹配的點或沒有邊連向的點,所以普遍是跑不滿的。
洛谷P3386 【模板】二分圖匹配

#include <bits/stdc++.h>
#define A 1010

using namespace std;
int g[A], n, m, e, ans; bool f[A][A], vis[A];
int find(int x) {
	for (int i = 1; i <= m; i++)
		if (f[x][i] and !vis[i]) { //如果有邊連向這個點並且這個點沒有被訪問過
			vis[i] = 1; //標記訪問,已經匹配過的點就不用再匹配了
			if (!g[i] or find(g[i])) { //如果它還沒有被匹配或協商之後可以給x騰出位置
				g[i] = x; //標記與哪個點匹配了
				return true;
			}
		}
	return false;
}
int main(int argc, char const *argv[]) {
	cin >> n >> m >> e; //n,m,e分別爲左圖點數,右圖點數和總邊數
	for (int i = 1, x, y; i <= e; i++) cin >> x >> y, f[x][y] = 1; //有邊就標記爲1
	for (int i = 1; i <= n; i++) if (find(i)) memset(vis, 0, sizeof vis), ans++; //對每個點找匹配對象
	cout << ans << endl; //vis要每次清空,vis標記的是一個右側點是否被匹配過
}

二分圖的最大匹配還可以直接用網絡流來做,DinicDinic的話複雜度Θ(nm)\Theta(n\sqrt{m})
具體做法就是在左邊建立超級源點,在右邊建立超級匯點,超級源點向左側點連邊,右側點向超級匯點連邊,中間的邊不變,邊的流量都是11,這個圖的最大流就是二分圖的最大匹配。

二分圖匹配中還有一個概念叫增廣路
增廣路是指,從一個未匹配點開始,經過若干個匹配點,最後到達對面集合的一個未匹配點的路徑。即這條路徑將兩個不同集合的兩個未匹配點通過一系列匹配點相連。將增廣路與原匹配的邊取反後可以得到一個更大的匹配,這裏的取反就是增廣路中的邊變成匹配的,之前匹配的邊變成未匹配的。
增廣路的路徑長度必定爲奇數,第一條邊和最後一條邊都不屬於當前匹配。奇數邊比偶數邊多一條,於是當我們把所有奇數邊都加到匹配子圖並把偶數邊都刪除,匹配數就會增加11
一個子圖MM爲原圖GG的最大匹配當且僅當不存在MM的增廣路徑。

  • 帶權二分圖匹配

上面的二分圖最大匹配可以看成每條邊的權值都是11,我們需要找到一個權值最大的匹配。
對於帶權的二分圖,它的最優匹配一定是一個完備匹配,就是說匹配到的點數是左右側點數的最小值。
由於是完備匹配,所以原先沒有的邊需要連上,邊權爲00即可。

專門求解帶權二分圖最優匹配的一種算法叫KMKM算法,可惜我並沒有學過,所以我會選擇用費用流來做帶權二分圖匹配。
二分圖問題是網絡流問題的特殊模型,所以基本都可以用網絡流的知識來做。

  • 最大獨立集

一個圖的獨立集是一個點集,其中這些點兩兩之間沒有邊相連。點數最多的獨立集叫這個圖的最大獨立集。
再介紹一個引申概念,圖的團。圖的團就是一些點兩兩之間都有邊相連。最大團就是點數最多的團。
一般圖的最大獨立集是NPNP問題,現在還沒有通用解法。但是對於特殊的二分圖就有做法。

下面是一些定理,也是結論,題目中可能會用到:

  1. 無向圖的最大團 = 這個圖補圖的最大獨立集
  2. 最大獨立集 = 點的總數 – 最小點覆蓋(最大匹配)
  • 最小支配集

支配集是一個點的集合,這些點與剩下的點之間都有邊相連,點數最少的支配集叫最小支配集。
用處不大,可以來看一下這個題P2899 手機網絡

  • 最小點覆蓋

點覆蓋是一個點的集合,使得所有邊都至少有一端與是點集中的點,點數最少的點覆蓋叫最小點覆蓋。
二分圖的最小點覆蓋 = 最大匹配
就不給證明了,記住結論也沒什麼不妥,網上也有不少證明,還是一個理解性的問題。

  • 最小路徑覆蓋

這裏的路徑覆蓋是指的DAGDAG的最小不相交路徑覆蓋,可相交路徑覆蓋需要用到傳遞閉包,不在此討論。
最小路徑覆蓋就是用最少的路徑條數,不重複不遺漏地覆蓋一個有向無環圖的所有頂點。

注意這裏就不侷限於二分圖了。
它的解法:首先將原圖中的每個點拆爲xxx+nx+n,原圖中的點在左側,拆出來的大於nn的點在右側,這樣又形成了一個二分圖。對於原圖中的邊(x,y)(x,y),在新建立的二分圖中連邊(x,y+n)(x,y+n),這樣建出來的圖叫拆點二分圖。
最小路徑覆蓋 = 原圖點數 – 拆點二分圖的最大匹配
對這個定理的簡單理解:將原圖拆成二分圖之後,每個點都是獨立的一個路徑,長度爲00,每連一條邊就會減少一條路徑,連邊的過程就是匹配的過程,所以要使路徑最少,匹配就要最大。
洛谷P2764 最小路徑覆蓋問題 \rightarrow 題解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章