A Systematic Approach to Algorithms

Vijay K. Garg · The University of Texas at Austin

Chapter 12. Bipartite Matching

Classical bipartite matching, vertex-cover, and chain-cover constructions.

This page: Classical forms. View LLP forms »

This page collects the classical / sequential implementations of the algorithms developed in this chapter. The lattice-linear (LLP) reformulations and chapter setup live on the LLP companion page.

BipartiteMatching

The classical sequential augmenting-path algorithm. tryMatch(u, ...) tries to match the left vertex $u$ via a DFS over the right side; if it succeeds, the path-toggling is folded into the recursion.

Time complexity: $O(n \cdot m)$ via the augmenting-path scheme, where $n$ is the number of left vertices and $m$ the number of edges.

int[] BipartiteMatching(int[][] adj) {
  int n = adj.length;
  int m = adj[0].length;
  int[] G       = new int[n];
  int[] partner = new int[m];
  int j = 0;
  while (j < m) {
    partner[j] = 0 - 1;
    j = j + 1;
  };
  int u = 0;
  while (u < n) {
    boolean[] seen = new boolean[m];
    if (tryMatch(u, adj, partner, seen)) {
      G[u] = 1;
    };
    u = u + 1;
  };
  return G;
}

boolean tryMatch(int u, int[][] adj, int[] partner, boolean[] seen) {
  int m = adj[0].length;
  int v = 0;
  while (v < m) {
    if (adj[u][v] == 1 && !seen[v]) {
      seen[v] = true;
      if (partner[v] == 0 - 1 || tryMatch(partner[v], adj, partner, seen)) {
        partner[v] = u;
        return true;
      }
    };
    v = v + 1;
  };
  return false;
}

VertexCoverFromMatching

King's-theorem construction in code: build a vertex cover of size $|M|$ in two parallel passes over the edges. Pass 1 puts every $L$-endpoint of $M$ into the cover. Pass 2 sweeps every uncovered edge $(u, v)$ with $u, v \notin C$, swapping the cover mark from a matched neighbour onto the uncovered endpoint.

Time complexity: $O(n + m)$.

boolean[] ParVertexCoverFromMatching(int[][] adj, int[] matchL) {
  int L = adj.length;
  int R = adj[0].length;
  boolean[] C       = new boolean[L + R];
  int[]     partner = new int[L + R];
  int i = 0;
  while (i < L + R) {
    partner[i] = 0 - 1;
    i = i + 1;
  };
  int u = 0;
  while (u < L) {
    int v = matchL[u];
    if (v != 0 - 1) {
      C[u]            = true;
      partner[u]      = L + v;
      partner[L + v]  = u;
    };
    u = u + 1;
  };
  u = 0;
  while (u < L) {
    int v = 0;
    while (v < R) {
      if (adj[u][v] == 1 && !C[u] && !C[L + v]) {
        if (partner[u] != 0 - 1) {
          C[partner[u]] = false;
          C[u]          = true;
        } else {
          C[partner[L + v]] = false;
          C[L + v]          = true;
        }
      };
      v = v + 1;
    };
    u = u + 1;
  };
  return C;
}