이분 매칭은 이분그래프에서의 매칭을 의미한다. HopcroftKarp 알고리즘을 이용하면 $O(E\sqrt{V})$에 풀 수 있지만, 여기서는 더 쉬운 알고리즘만을 다루겠다. DFS를 활용하면 $O(VE)$로 최대 이분 매칭을 구할 수 있다.
참고.
- 일반 그래프에서의 매칭은 더 어려운 문제이다. blossom 알고리즘을 이용하면 $O(V^2E)$에 된다고 한다.
- weighted bipartite matching은 MCMF를 활용하여 풀 수 있다.
DFS를 사용한 알고리즘은 상당히 간단하다. 이분 그래프를 $G=(L, R, E)$라 하자. $L, R$은 정점의 집합이다. $L$에 속한 정점을 차례대로 보면서 매칭을 추가해줄 것이다. $v \in L$에 대해 $v$와 연결된 정점 $u \in R$을 본다. $u$가 여태까지 구한 매칭에 속하지 않는다면 이어주면 된다. 이미 속한다면, $u$가 매칭으로 이어져있는 정점 $p$에 대해 $p-u$ 매칭을 끊고 $v-u$를 연결한다. 그 후 $p$에 대해 다시 매칭을 찾아본다. dfs로 이 과정을 반복한다. $p$에 대해 새로운 매칭을 찾는 것에 실패했다면, 다시 $p-u$를 연결해주고 다른 매칭을 찾아본다. dfs 과정에서 이미 지나온 정점에는 가지 않도록 해주어야 한다. 만약 dfs가 끝났는데도 새로운 매칭을 찾지 못했다면, 이 정점들로는 새로운 매칭을 찾을 수 없는 것이다. 이 과정을 $L$의 모든 정점에 대해 반복하면 된다.
아래 링크 참고.
https://jason9319.tistory.com/149
http://blog.naver.com/PostView.nhn?blogId=kks227&logNo=220807541506
내 코드
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 105;
vector<int> ed[MAXN];
int p[MAXN]; // R의 각 정점이 매칭된 L의 정점
bool chk[MAXN]; // L의 각 정점을 dfs 과정에서 이미 보았는가
bool f(int x) {
if(x == -1) return true;
if(chk[x]) return false;
chk[x] = true;
for(auto a : ed[x]) {
int t = p[a];
p[a] = x; // 매칭을 끊고 뺐어온다
if(f(t)) return true; // 매칭 성공
p[a] = t; // 복구시킨다
}
return false;
}
int main() {
//TODO
memset(p, -1, sizeof(p));
int ans = 0;
for(int i = 1; i <= N; i++) {
memset(chk, 0, sizeof(chk));
if(f(i)) ans++; // 매칭 성공
}
//TODO
}
'알고리즘' 카테고리의 다른 글
양수 가중치를 가지는 그래프에서 O(V+cE)로 최단경로 구하기 (1) | 2019.10.15 |
---|---|
0-1 BFS (0) | 2019.10.14 |
Heavy-Light Decomposition (HLD) (0) | 2019.10.12 |
Centroid Decomposition (0) | 2019.10.11 |
SOS dp (Sum over Subsets) (0) | 2019.09.28 |