---
# System prepended metadata

title: 二分圖、匹配、匈牙利算法
tags: [圖論]

---

---
tags: 圖論
title: 二分圖、匹配、匈牙利算法
---
:::warning
## [vector存圖法](https://www.notion.so/vector-f437fa3263f840c1a21cdebe5d4384ce)
:::

:::info
- #### 模板題 [ZJ c889](https://zerojudge.tw/ShowProblem?problemid=c889)
- #### 模板題 [TIOJ 1209](https://tioj.ck.tp.edu.tw/problems/1209)
- #### [CF 557D](https://codeforces.com/problemset/problem/557/D)
- #### [CF 1144F](https://codeforces.com/problemset/problem/1144/F)
:::

:::success
# 二分圖 Bipartite Graph
![](https://i.imgur.com/TBG6KNM.png)

## 定義
- 將所有點分成兩個集合，不存在連接同集合中兩點的邊

## 判定
- 著色法：
  - 使用DFS以兩個顏色著色，嘗試將任意相鄰兩點塗上不同顏色
  - 如果發現有一點跟「相鄰且已經塗色的點」同一顏色，則二分圖不成立，反之成立

- 實作：
  - 紀錄每個點的顏色（紅、藍、未塗色），並使用DFS走訪塗色＋判定
:::

:::success
# 匹配 Matching

## 定義

![](https://i.imgur.com/QtD9uGl.png)

- 在圖上找一組邊，任兩條邊沒有公用點

- 完美匹配、最大匹配、最大邊權匹配。。。

# 匈牙利算法 Hungarian algorithm

- #### [ZJ c455](https://zerojudge.tw/ShowProblem?problemid=c455)
- #### [UVA 10080](https://onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=1021)

## 用途

- 無邊權二分圖上找最大匹配(邊數最多)

### 交替路徑和增廣路徑

- 交替路徑：選一個點當起點，沿著(邊)未匹配、匹配交替走

1 -> 5 -> 2
![](https://i.imgur.com/QtD9uGl.png)
未匹配、匹配邊對調，匹配數不變


- 增廣路徑：在走交替路徑的途中遇到未匹配的點(兩端皆未匹配)

1 -> 7 -> 4 -> 8
![](https://i.imgur.com/u7R6k8W.png)
未匹配、匹配邊對調，匹配數+1

## 匈牙利樹

- 從一個點開始走交替路徑直到無法再擴展為止，且葉節點已匹配，形成的樹

![](https://i.imgur.com/HaJlNzt.png)

## 實作

- 找到增廣路徑 -> 對調匹配、未匹配邊

- 找到匈牙利樹 -> 刪除(不看)

- 無增廣路徑即為最大匹配
:::

:::success
# 網路流實作二分圖匹配

## 最大基數匹配(Maximum cardinality bipartite matching)
![](https://i.imgur.com/9LcKH2w.jpg)

### 將問題轉化成最大流問題

1. 增加源點s與匯點t

2. 建立弧連接s和X中每一點，方向由s指向X

3. 建立弧連接$t$和Y中每一點，方向由Y指向t

4. 將原二分圖中的每條邊改為弧，方向由X指向Y

5. 將每條弧容量設定為1

- 求最大流，路徑中原圖的邊形成的邊集即為最大基數匹配

## 最大權完美匹配(Maximum weighted perfect matching)

### 將問題轉化為最大費用最大流問題

1. 增加源點$s$與匯點$t$

2. 建立弧連接$s$和X中每一點，方向由$s$指向X，==容量設定為1，費用設定為0==

3. 建立弧連接$t$和Y中每一點，方向由Y指向$t$，==容量設定為1，費用設定為0==

4. 將原二分圖中的每條邊改為弧，方向由X指向Y，==容量設定1，費用設定為原邊權==

- 求最大費用最大流，路徑中原圖的邊形成的邊集即為最大權完美匹配
:::