home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************
- +
- + LEDA 2.1.1 11-15-1991
- +
- +
- + _mcb_matching.c
- +
- +
- + Copyright (c) 1991 by Max-Planck-Institut fuer Informatik
- + Im Stadtwald, 6600 Saarbruecken, FRG
- + All rights reserved.
- +
- *******************************************************************************/
-
-
-
- /*******************************************************************************
- * *
- * MAX_CARD_BIPARTITE_MATCHING (maximum cardinality bipartite matching) *
- * *
- *******************************************************************************/
-
-
-
- #include <LEDA/graph_alg.h>
-
- edge find_next_augmenting_path(graph&,node, node, node_array(edge)&, node_array(int)&);
- /* defined later */
-
- list(edge) MAX_CARD_BIPARTITE_MATCHING(graph& G, const list(node)& A,
- const list(node)& B )
- { // G is a bipartite graph with sides A and B, all edges must be directed
- // from A to B. We compute a matching of maximum cardinality using the
- // algorithm of Hopcroft and Karp. The running time is O(sqrt(n)*m).
-
- node v;
- edge e;
-
- forall(v,B)
- forall_adj_edges(e,v)
- { error_handler(0,"mcb_matching: edge from B to A (deleted).");
- G.del_edge(e);
- }
-
- node s = G.new_node("s");
- node t = G.new_node("t");
-
- forall(v,A) G.new_edge(s,v);
- forall(v,B) G.new_edge(v,t);
-
- node_array(edge) pred(G,0);
- node_array(int) layer(G,0);
- list(edge) EL;
- list(node) L;
-
- G.reset();
-
- for(;;)
- { forall_nodes(v,G) { layer[v] = -1; pred[v] = 0; }
-
- L = BFS(G,s,layer);
-
- if (layer[t]>=0) // there is at least one augmenting path
- { while (e = find_next_augmenting_path(G,s,t,pred,layer)) EL.append(e);
-
- G.reset();
- while (e=EL.pop())
- { edge x = pred[source(e)];
- while (source(x) != s)
- { G.rev_edge(x);
- x=pred[target(x)];
- }
- G.del_edge(e); // edge into t
- G.del_edge(x); // edge out of s
- }
- }
- else break;
- }
-
- list(edge) result;
-
- forall(v,B)
- forall_adj_edges(e,v)
- if (target(e) != t)
- result.append(e);
- else
- EL.append(e);
-
- //restore graph:
- forall(e,EL) G.del_edge(e);
- forall(e,result) G.rev_edge(e);
- G.del_node(s);
- G.del_node(t);
-
- return result;
- }
-
-
- // edges in the layered network are called eligible:
- #define ELIGIBLE(e)\
- (layer[target(e)]==layer[source(e)]+1) && (layer[target(e)]<=layer[t])
-
-
- edge find_next_augmenting_path(graph& G, node s, node t, node_array(edge)& pred,
- node_array(int)& layer)
- { node w;
- edge e;
- edge f=0;
-
- while (f==0 && G.next_adj_edge(e,s))
- if (ELIGIBLE(e))
- if ((w=target(e))==t) f=e; // t is reached
- else if (pred[w]==0) // w not reached before
- { pred[w] = e;
- f = find_next_augmenting_path(G,w,t,pred,layer);
- }
- return f;
- }
-
-
-
-