About Bipartite Graph
— 225 陳澔樂
一張圖如果可以分成兩團,且每一團裡面都互不相連,他就是二分圖
作一次dfs,將圖塗色
如果需要三種以上顏色的話
就不是,不然就是
bool dfs(int cur) {
for(auto e : edge[cur]){
if(!color[e]){
color[e] = 3-color[cur];
if(!dfs(e)) return 0;
}else if(color[e]==color[cur]){
return 0;
}
}
return 1;
}
怎麼作?
把一個點拆成兩個點
一個匹配是一個圖中邊的集合P
使得每兩條在P的邊都沒有共同頂點
:為什麼要二分圖
因為我也不會一般圖
因為這堂課叫做二分圖
二分圖很有用阿
:這個東西可以用 flow 做吧
算法先備知識:
算法先備知識:
Berge's Theorem:
若有一個匹配沒有一條擴增路徑,他一定是最大匹配
算法先備知識:
Berge's Theorem:
證明:
考慮反例 有一個匹配沒有擴增路徑,且他不是最大匹配 叫他 S 使其中一個最大匹配為 B
將S中的邊和B中的邊取出來 形成一個新的圖P(只有S和B中的邊的圖,節點不變) p.s. 圖p可能不是連通的
我們把原本在S裡面的邊塗黑 B中的塗白,在S和B中的塗灰 我們需要證明白邊不會比黑邊多
分開討論區塊情況
剩下的情況是只有白邊和黑邊的很多個區域
他可以長什麼樣子?
性質1 P中沒有一個節點的度數超過2
沒有一個點可以有兩個同一種顏色的邊,又只有兩種顏色
根據性質1 ,區域只能長兩種樣子:
第一種是白黑交替的直鏈,第二種是白黑交替環
如果是白黑交替環→環的邊數一定是偶數(需要交替) → (白==黑)
如果是直鏈那又有三種情況→ 頭尾都是黑,頭尾都是白,頭尾不同色
所以白邊不比黑邊多,證畢
所以我們知道,沒有擴充路徑就是最大匹配了,那如何設計演算法?
一直找擴充路徑直到找不到為止
演算法
bool vis[MAXN2];/*是否走訪過*/
bool dfs(int u){//是否有擴增路徑
for(size_t i=0;i<g[u].size();++i){
int v=g[u][i];
if(vis[v])continue;
vis[v]=1;
if(match[v]==-1||dfs(match[v])){//如果過去的那個點沒有匹配邊或從那個點的匹配點出發有擴增路徑就有
match[v]=u;
return 1;
}
}
return 0;
}
演算法
int ans=0;
fill(match,match+n2,-1);
for(int i=0;i<n1;++i){
fill(vis,vis+n2,0);
if(dfs(i))++ans;
}
return ans;
演算法
複雜度
我一開始就說我不會了
對於所有圖來說
|最大匹配| + |最小邊覆蓋|=|最小點覆蓋| + |最大獨立集|= |V|
對於二分圖來說
|最大匹配| =|最小點覆蓋|
每一條邊都要被覆蓋=>所有匹配邊都至少貢獻1點
然後我們可以構造出一個和最大匹配一樣大的最小點覆蓋
將二分圖分成L和R
從L的未匹配點開始走交替路徑DFS
選碰不到的在L的點和碰得到的在R的點
形成點覆蓋
這樣的交替路徑會是
L->未匹配邊->R->匹配邊->L.....
這個點集合大小和最大匹配一樣
因為L中選的點都有匹配(不然會從他開始DFS,會碰到)
R中選的點都有匹配(不然會有擴充路徑)
兩者的匹配邊不會重複(不然L中的點會被DFS碰到)
這個東西真的是點覆蓋
因為假設有一邊(x,y)使得x和y都沒被選到
這個邊不能是匹配邊
(因為上一頁證明所有匹配邊都洽有一個點被選到)
也不能是非匹配邊
(因為這代表x可以走到y)
表示這個邊不存在
所以我們知道他真的是點覆蓋且大小和最大匹配一樣
又最小點覆蓋沒辦法小於最大匹配
這個東西是最小點覆蓋
證畢
KM算法
KM算法
這個演算法算的是一張二分圖的最大權完美匹配
可以用前面的方法變成最大權匹配
KM算法
定義
頂標:
要用KM算法 我們要先引入頂標
KM算法
頂標
他有一個性質
如果可以找到所有合法頂標和中的最小值
就可以找到最大權完美匹配
KM算法
此時頂標和一定是最小值
(比他更小表示有一合法頂標方法比一個匹配權重和小)
表示G`的完美匹配為G的最大權完美匹配
將E`的邊稱為緊邊 G`稱為緊邊子圖
KM算法
增加匹配大小就在G′找增廣路徑就好了。
第二點要怎麼做到?
KM算法
考慮剛剛最小點覆蓋的東東
我們在G`上找到最小點覆蓋
KM算法
KM算法
KM算法
或是用MCMF也是O(n³)
如果我連不帶權的都不會了
你為甚麼覺得我會帶權的
題目
PCCORZ