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.
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 :)
ReplyDeletehello. i would like to know what the input data is. thank you in advance!
ReplyDeleteHi ,i'm from Vietnam.
ReplyDeleteYes this works, I think. I used it in a problem:
ReplyDeleteMATCHING @ 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 :)
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 ?
ReplyDeleteNIL 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.
ReplyDeleteI tried the sample input
ReplyDelete5 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?
I wrote the following main() to work with your code:
ReplyDeleteint 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?
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.
ReplyDeleteYes, it's my mistake, in the main function. Thanks.
ReplyDeleteNo problem.
ReplyDeletewould you please help me...i'm trying to solve this problem https://www.spoj.pl/problems/MATCHING and i got WA
ReplyDeletecould you please give me some more test case...thanks.. :)