Luzhiled's Library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub ei1333/library

:heavy_check_mark: Bipartite-Matching(二部グラフの最大マッチング) (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$ のマッチングといい, 辺の本数が最大であるマッチングを最大マッチングという.

ここでは, 二部グラフの最大マッチングを最大流のアルゴリズムを利用して求める.

計算量

Verified with

Code

/**
 * @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;
      }
    }
  }
};
Back to top page