TOP > グラフ 二部グラフの最大マッチング
二部グラフの最大マッチング(Hopcroft-Karp)
説明
二部グラフの最大マッチングを求める。
計算量
- O(E√V)
実装例
- HopcroftKarp(n, m):= 一方の頂点数を n, もう一方の頂点数を m で初期化する。
- add_edge(u, v):= 頂点 u,v 間に辺を張る。
- bipartite_matching():= 二部グラフの最大マッチングを返す。
Copy
struct HopcroftKarp {
vector< vector< int > > graph;
vector< int > dist, match;
vector< bool > used, vv;
HopcroftKarp(int n, int m) : graph(n), match(m, -1), used(n) {}
void add_edge(int u, int v) {
graph[u].push_back(v);
}
void bfs() {
dist.assign(graph.size(), -1);
queue< int > que;
for(int i = 0; i < graph.size(); i++) {
if(!used[i]) {
que.emplace(i);
dist[i] = 0;
}
}
while(!que.empty()) {
int a = que.front();
que.pop();
for(auto &b : graph[a]) {
int c = match[b];
if(c >= 0 && dist[c] == -1) {
dist[c] = dist[a] + 1;
que.emplace(c);
}
}
}
}
bool dfs(int a) {
vv[a] = true;
for(auto &b : graph[a]) {
int c = match[b];
if(c < 0 || (!vv[c] && dist[c] == dist[a] + 1 && dfs(c))) {
match[b] = a;
used[a] = true;
return (true);
}
}
return (false);
}
int bipartite_matching() {
int ret = 0;
while(true) {
bfs();
vv.assign(graph.size(), false);
int flow = 0;
for(int i = 0; i < graph.size(); i++) {
if(!used[i] && dfs(i)) ++flow;
}
if(flow == 0) return (ret);
ret += flow;
}
}
void output() {
for(int i = 0; i < match.size(); i++) {
if(~match[i]) {
cout << match[i] << "-" << i << endl;
}
}
}
};
検証
Copy
#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_7_A"
#include "../../template/template.cpp"
#include "../template.cpp"
#include "../hopcroft-karp.cpp"
int main() {
int X, Y, E;
scanf("%d %d %d", &X, &Y, &E);
HopcroftKarp bm(X, Y);
for(int i = 0; i < E; i++) {
int a, b;
scanf("%d %d", &a, &b);
bm.add_edge(a, b);
}
printf("%d\n", bm.bipartite_matching());
}