Friday, May 7, 2010

Maximum Matching (Hopcroft)


Hopcroft-Karp is one of the fastest algorithm that finds the maximum cardinality matching on a bipartite graph. It has the best known worst case time complexity. More details can be found here [courtesy of Wikipedia].

C++ Source Code:



#define MAX 100001
#define NIL 0
#define INF (1<<28)

vector< int > G[MAX];
int n, m, match[MAX], dist[MAX];
// n: number of nodes on left side, nodes are numbered 1 to n
// m: number of nodes on right side, nodes are numbered n+1 to n+m
// G = NIL[0] ∪ G1[G[1---n]] ∪ G2[G[n+1---n+m]]

bool bfs() {
int i, u, v, len;
queue< int > Q;
for(i=1; i<=n; i++) {
if(match[i]==NIL) {
dist[i] = 0;
Q.push(i);
}
else dist[i] = INF;
}
dist[NIL] = INF;
while(!Q.empty()) {
u = Q.front(); Q.pop();
if(u!=NIL) {
len = G[u].size();
for(i=0; i<len; i++) {
v = G[u][i];
if(dist[match[v]]==INF) {
dist[match[v]] = dist[u] + 1;
Q.push(match[v]);
}
}
}
}
return (dist[NIL]!=INF);
}

bool dfs(int u) {
int i, v, len;
if(u!=NIL) {
len = G[u].size();
for(i=0; i<len; i++) {
v = G[u][i];
if(dist[match[v]]==dist[u]+1) {
if(dfs(match[v])) {
match[v] = u;
match[u] = v;
return true;
}
}
}
dist[u] = INF;
return false;
}
return true;
}

int hopcroft_karp() {
int matching = 0, i;
// match[] is assumed NIL for all vertex in G
while(bfs())
for(i=1; i<=n; i++)
if(match[i]==NIL && dfs(i))
matching++;
return matching;
}

The implementation is quite straight forward as the algorithm on Wikipedia page. I am looking for some optimizations.

12 comments:

  1. This works? Do you have a testing program also? please post it because i just can't figure where the problem is. Maybe at me :)

    ReplyDelete
  2. hello. i would like to know what the input data is. thank you in advance!

    ReplyDelete
  3. Yes this works, I think. I used it in a problem:
    MATCHING @ SPOJ
    https://www.spoj.pl/problems/MATCHING

    Sorry I don't have any testing program yet.

    I am learning matching for only a few days, so may be this is not a source which will solve any problem of matching, but I think it could be modified accordingly.

    Thanks :)

    ReplyDelete
  4. But what is NIL node ? Is it an extra node that must be added in the graph before we launch the algorithm ? In this case how are NIL node edges defined ? NIL node has no edges ?

    ReplyDelete
  5. NIL node is nothing but just a reference node, it is added to the graph prior to applying the algorithm. As you see, it has no particular use in the algorithm, except used as a marking item, i.e. whether some node has some match or not. G[0] is left blank (no edge) and NIL has the value 0, so, we are calling Node with number 0 to be a NIL node. I tried to stick to the original algorithm presented at wikipedia, the actual implementations are more straight forward, but those are specific problem dependent.

    ReplyDelete
  6. I tried the sample input

    5 4 6
    5 2
    1 2
    4 3
    3 1
    2 2
    4 4

    for the following main():

    int main() {
    int A, B;

    scanf("%d %d %d", &N, &M, &P);
    while (P--) {
    scanf("%d %d", &A, &B);
    G[A].push_back(B);

    }

    printf("%d\n", hopcroft_karp());


    return 0;
    }

    It gives 2, correct answer is 3.

    What's wrong with the main? or what's missing?

    ReplyDelete
  7. I wrote the following main() to work with your code:

    int main() {
    int A, B, P;

    scanf("%d %d %d", &N, &M, &P);
    while (P--) {
    scanf("%d %d", &A, &B);
    G[A].push_back(B);

    }

    printf("%d\n", hopcroft_karp());


    return 0;
    }

    It gives 2, correct answer is 3.

    What's wrong with the main() function? or what's missing?

    ReplyDelete
  8. Sorry, can't say without reading the whole code. However, this implementation is well tested as well. Although the right portion of the graph is not necessary.

    ReplyDelete
  9. Yes, it's my mistake, in the main function. Thanks.

    ReplyDelete
  10. would you please help me...i'm trying to solve this problem https://www.spoj.pl/problems/MATCHING and i got WA
    could you please give me some more test case...thanks.. :)

    ReplyDelete

Catagories

academic study (17) access modifiers (1) algorithm (28) bash (1) beginner (17) bfs (1) bigint (1) binary tree (1) bitwise (4) blogger (5) bpm (2) brainfuck (1) bst (1) c (1) c++ (36) changes (1) character device driver (1) combinatorics (2) command prompt (1) comparator (1) compression (1) computational geometry (2) confusion (1) contest (7) crc (1) cse (3) css (1) customize (1) data structure (10) database (1) decoding (1) design (1) device driver (1) divide and conquer (2) dp (3) driver (1) dynamic programming (9) encoding (1) encryption (1) error (2) esoteric language (2) euler circuit (1) euler path (1) executable (1) expression evaluation (1) extended euclid (1) facebook (1) factorization (1) funny (14) gcd (2) geometry (4) git (1) github (1) graph (7) hashing (1) hiding window (1) hints (5) hopcroft karp (1) huffman (1) jar (1) java (5) javascript (1) jdbc (1) kernel programming (2) lab (1) like (1) linear algebra (3) linux (5) ls (1) makefile (1) math (16) matrix (2) matrix algebra (1) matrix exponentiation (1) matrix multiplication (1) maxflow (1) maximum bipartite matching (2) maximum flow (1) merge sort (3) mistake (1) modular arithmatic (1) module compiling (2) mysql (1) number system (1) number theory (8) online judge (3) operating system (1) os (1) other (8) parallel programming (1) pollard rho (1) primes (3) problem (3) problem classifier (2) problem solving (34) programming (51) pthreaded (1) puzzle (1) python (3) recursion (5) repository (1) shell (1) shell script (1) sieve (1) simulation (1) sort (3) spacing (1) sphere online judge (12) spoj (12) syntax highlighting (1) system programming (4) table tag (1) tc (1) template (4) thread (1) topcoder (1) training (3) tree (1) tutorial (2) ubuntu (1) usaco (1) uva (5) uva online judge (5) vector (1) windows (1)