home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************
- +
- + LEDA 2.1.1 11-15-1991
- +
- +
- + _mwb_matching.c
- +
- +
- + Copyright (c) 1991 by Max-Planck-Institut fuer Informatik
- + Im Stadtwald, 6600 Saarbruecken, FRG
- + All rights reserved.
- +
- *******************************************************************************/
-
-
-
- /*******************************************************************************
- * *
- * MAX_WEIGHT_BIPARTITE_MATCHING (maximum weight bipartite matching) *
- * *
- *******************************************************************************/
-
-
-
- #include <LEDA/graph_alg.h>
-
-
- // for integer edge weights:
-
- list(edge) MAX_WEIGHT_BIPARTITE_MATCHING (graph& G,
- const list(node)& A,
- const list(node)& B,
- const edge_array(int)& weight )
-
- {
-
- node v;
- edge e;
-
- forall(v,B)
- forall_adj_edges(e,v)
- { error_handler(0,"mwb_matching: edge from B to A (deleted)");
- G.del_edge(e);
- }
-
- node s = G.new_node();
-
- node_array(int) dist(G);
- node_array(int) u(G,0);
- node_array(edge) pred(G);
-
-
- forall(v,A)
- { int m = 0;
- forall_adj_edges(e,v) if (weight[e] > m) m = weight[e];
- if (m > 0) G.new_edge(s,v);
- u[v] = m;
- }
-
- edge_array(int) p(G,0);
-
-
- while (outdeg(s) > 0)
- {
- forall_edges(e,G)
- { p[e] = u[source(e)] + u[target(e)];
- if (source(e) != s) p[e] -= weight[e];
- }
-
- DIJKSTRA(G,s,p,dist,pred);
-
- node j0,i0;
- int min_A = Infinity;
- int min_B = Infinity;
-
- forall(v,B)
- { int x = dist[v];
-
- if ( outdeg(v)==0 && x < min_A )
- { j0 = v;
- min_A = x;
- }
-
- }
-
- forall(v,A)
- { int x = dist[v];
- int y = x+u[v];
-
- if ( x < Infinity && y < min_B )
- { i0 = v;
- min_B = y;
- }
-
- }
-
- node k0 = j0;
- int d = min_A;
- if (min_A > min_B) { k0 = i0; d = min_B; }
-
- forall(v,A) if (d > dist[v]) u[v] -= d-dist[v];
- forall(v,B) if (d > dist[v]) u[v] += d-dist[v];
-
- if (e = pred[k0])
- { while (source(e) != s)
- { G.rev_edge(e); /* "source(e) heisst jetzt target(e)" */
- e=pred[target(e)];
- }
- G.del_edge(e);
- }
- }
-
- edgelist result;
- forall(v,B) forall_adj_edges(e,v) result.append(e);
-
- // restore graph
- G.del_node(s);
- forall(e,result) G.rev_edge(e);
-
- return result;
- }
-
-
-
-
- #ifndef NO_REAL_GRAPH_ALG
-
- // for real edge weights:
-
- list(edge) MAX_WEIGHT_BIPARTITE_MATCHING (graph& G,
- const list(node)& A,
- const list(node)& B,
- const edge_array(real)& weight )
-
- {
-
- node v;
- edge e;
-
- forall(v,B)
- forall_adj_edges(e,v)
- { error_handler(0,"mwb_matching: edge from B to A (deleted)");
- G.del_edge(e);
- }
-
- node s = G.new_node();
-
- node_array(real) dist(G);
- node_array(real) u(G,0);
- node_array(edge) pred(G);
-
-
- forall(v,A)
- { real m = 0;
- forall_adj_edges(e,v) if (weight[e] > m) m = weight[e];
- if (m > 0) G.new_edge(s,v);
- u[v] = m;
- }
-
- edge_array(real) p(G,0);
-
- // edge_array(real) w(G,0);
- // forall_edges(e,G) if (source(e)!=s) w[e] = weight[e];
-
-
- while (outdeg(s) > 0)
- {
-
- /* forall_edges(e,G) p[e] = u[source(e)] + u[target(e)] - w[e]; */
-
- forall_edges(e,G)
- { p[e] = u[source(e)] + u[target(e)];
- if (source(e) != s) p[e] -= weight[e];
- }
-
- DIJKSTRA(G,s,p,dist,pred);
-
- node j0,i0;
- real min_A = Infinity;
- real min_B = Infinity;
-
- forall(v,B)
- if ((outdeg(v)==0)&&(dist[v] < min_A))
- { j0 = v;
- min_A = dist[v];
- }
-
- forall(v,A)
- if (dist[v] < Infinity && (dist[v]+u[v]) < min_B)
- { i0 = v;
- min_B = dist[v] + u[v];
- }
-
- node k0 = j0;
- real d = min_A;
- if (min_A > min_B) { k0 = i0; d = min_B; }
-
- forall(v,A) if (d > dist[v]) u[v] -= d-dist[v];
- forall(v,B) if (d > dist[v]) u[v] += d-dist[v];
-
- if (e = pred[k0])
- { while (source(e) != s)
- { G.rev_edge(e); /* "source(e) heisst jetzt target(e)" */
- e=pred[target(e)];
- }
- G.del_edge(e);
- }
- }
-
- edgelist result;
- forall(v,B) forall_adj_edges(e,v) result.append(e);
-
- // restore graph
- G.del_node(s);
- forall(e,result) G.rev_edge(e);
-
- return result;
- }
-
-
- #endif
-