This documentation is automatically generated by online-judge-tools/verification-helper
#include "graph/flow/bipartite-matching.hpp"
グラフ $G=(V, E)$ において, $V$ が $2$ つの部分集合 $X$ と $Y$ に分割され, $E$ のどの辺も一方の端点は $X$ に, もう一方の端点は $Y$ に属しているとき, $G$ を二部グラフという.
グラフ $G=(V, E)$ において, $M$ が $E$ の部分集合でかつ $M$ のどの $2$ 辺も共通の端点をもたないとき, $M$ を $G$ のマッチングといい, 辺の本数が最大であるマッチングを最大マッチングという.
ここでは, 二部グラフの最大マッチングを最大流のアルゴリズムを利用して求める.
BipartiteMatching(n)
:= 全体のグラフの頂点数を n
で初期化する.add_edge(u, v)
:= 頂点 u
, v
間に辺を張る.bipartite_matching()
:= 二部グラフの最大マッチングを返す.add_vertex(idx)
:= 頂点 idx
を追加し, フローの変化量を返す($0$ または $1$).erase_vertex(idx)
:= 頂点 idx
を削除し, フローの変化量を返す($0$ または $-1$).output()
:= マッチングに使った辺を出力する./**
* @brief Bipartite-Matching(二部グラフの最大マッチング)
*
*/
struct BipartiteMatching {
vector< vector< int > > graph;
vector< int > alive, used, match;
int timestamp;
explicit BipartiteMatching(int n) : graph(n), alive(n, 1), used(n, 0), match(n, -1), timestamp(0) {}
void add_edge(int u, int v) {
graph[u].push_back(v);
graph[v].push_back(u);
}
bool augment(int idx) {
used[idx] = timestamp;
for(auto &to : graph[idx]) {
int to_match = match[to];
if(alive[to] == 0) continue;
if(to_match == -1 || (used[to_match] != timestamp && augment(to_match))) {
match[idx] = to;
match[to] = idx;
return true;
}
}
return false;
}
int bipartite_matching() {
int ret = 0;
for(int i = 0; i < (int) graph.size(); i++) {
if(alive[i] == 0) continue;
if(match[i] == -1) {
++timestamp;
ret += augment(i);
}
}
return ret;
}
int add_vertex(int idx) {
alive[idx] = 1;
++timestamp;
return augment(idx);
}
int erase_vertex(int idx) {
alive[idx] = 0;
if(match[idx] == -1) {
return 0;
}
match[match[idx]] = -1;
++timestamp;
int ret = augment(match[idx]);
match[idx] = -1;
return ret - 1;
}
void output() const {
for(int i = 0; i < (int) graph.size(); i++) {
if(i < match[i]) {
cout << i << "-" << match[i] << endl;
}
}
}
};
#line 1 "graph/flow/bipartite-matching.hpp"
/**
* @brief Bipartite-Matching(二部グラフの最大マッチング)
*
*/
struct BipartiteMatching {
vector< vector< int > > graph;
vector< int > alive, used, match;
int timestamp;
explicit BipartiteMatching(int n) : graph(n), alive(n, 1), used(n, 0), match(n, -1), timestamp(0) {}
void add_edge(int u, int v) {
graph[u].push_back(v);
graph[v].push_back(u);
}
bool augment(int idx) {
used[idx] = timestamp;
for(auto &to : graph[idx]) {
int to_match = match[to];
if(alive[to] == 0) continue;
if(to_match == -1 || (used[to_match] != timestamp && augment(to_match))) {
match[idx] = to;
match[to] = idx;
return true;
}
}
return false;
}
int bipartite_matching() {
int ret = 0;
for(int i = 0; i < (int) graph.size(); i++) {
if(alive[i] == 0) continue;
if(match[i] == -1) {
++timestamp;
ret += augment(i);
}
}
return ret;
}
int add_vertex(int idx) {
alive[idx] = 1;
++timestamp;
return augment(idx);
}
int erase_vertex(int idx) {
alive[idx] = 0;
if(match[idx] == -1) {
return 0;
}
match[match[idx]] = -1;
++timestamp;
int ret = augment(match[idx]);
match[idx] = -1;
return ret - 1;
}
void output() const {
for(int i = 0; i < (int) graph.size(); i++) {
if(i < match[i]) {
cout << i << "-" << match[i] << endl;
}
}
}
};