_mc_matching.c
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:10k
开发平台:

MultiPlatform

  1. /*******************************************************************************
  2. +
  3. +  LEDA-R  3.2.3
  4. +
  5. +  _mc_matching.c
  6. +
  7. +  Copyright (c) 1995  by  Max-Planck-Institut fuer Informatik
  8. +  Im Stadtwald, 66123 Saarbruecken, Germany     
  9. +  All rights reserved.
  10. *******************************************************************************/
  11. /*******************************************************************************
  12. *
  13. *  MAX_CARD_MATCHING  (maximum cardinality matching)
  14. *
  15. *  An implementation of Edmonds' algorithm 
  16. *
  17. *
  18. *  J. Edmonds:  Paths, trees, and flowers 
  19. *               Canad. J. Math., Vol. 17, 1965, 449-467
  20. *
  21. *  R.E. Tarjan: Data Structures and Network Algorithms,
  22. *               CBMS-NFS Regional Conference Series in Applied Mathematics,
  23. *               Vol. 44, 1983
  24. *
  25. *
  26. *  running time: O(n*m*alpha(n))
  27. *
  28. *
  29. *  S. Naeher (October 1991)
  30. *
  31. *******************************************************************************/
  32. #include <LEDA/graph_alg.h>
  33. #include <LEDA/node_partition.h>
  34. enum LABEL {ODD, EVEN, UNREACHED};
  35. static int cmp_degree(const node& v,const node& w)  // compare indeg of v and w
  36. { return indeg(v) - indeg(w); }
  37. static int greedy( graph &G, node_array<node>& mate )   // greedy heuristic
  38. { node v;
  39.   int count = 0;
  40.   forall_nodes(v,G)
  41.     if (mate[v] == nil)
  42.     { edge e;
  43.       forall_adj_edges(e,v)
  44.       { node w = target(e);
  45.         if (v != w && mate[w] == nil) 
  46.         { mate[v] = w;
  47.           mate[w] = v;
  48.           count++;
  49.           break;
  50.          }
  51.        }
  52.      }
  53.    return count;
  54.  }
  55. static void heuristic( graph &G, node_array<node>& mate )
  56. {
  57.  // Heuristic (Markus Paul):
  58.  // finds almost all augmenting paths of length <=3 with two passes over
  59.  // the adjacency lists
  60.  // ("almost": discovery of a blossom {v,w,x,v} leads to a skip of the
  61.  // edge (x,v), even if the base v stays unmatched - it's not worth while
  62.  // to fix this problem)
  63.  // if all adjacent nodes w of v are matched, try to find an other 
  64.  // partner for mate[x], and match v and w on success
  65.   node u,v;
  66.   bool found;
  67.   node_array<int> all_matched(G,false);
  68.   forall_nodes( v, G )
  69.   {
  70.     edge e = G.first_adj_edge(v);
  71.     if( mate[v]==nil )
  72.     {
  73.         while(e != nil && mate[target(e)]!=nil) e = G.adj_succ(e);
  74.         if( e != nil ) 
  75.           { mate[v] = target(e);  
  76.             mate[target(e)] = v ;  
  77.            }
  78.         else // second pass
  79.           {
  80.     all_matched[v] = true;
  81.             forall_adj_edges(e,v)
  82.             {
  83.               node w = target(e);
  84.               node x = mate[w];
  85.     
  86.               if( ! all_matched[x] ) 
  87.               {
  88.                 while((found=G.next_adj_node(u,x)) && (u==v || mate[u]!=nil));
  89.     
  90.                 if( found ) 
  91.                   { mate[u] = x;  mate[x] = u ;
  92.                     mate[v] = w;  mate[w] = v ;
  93.                     G.init_adj_iterator(x);
  94.                     break;
  95.                 }
  96.         else
  97.                    all_matched[x] = true;
  98.                }
  99.              }
  100.            }
  101.         } 
  102.     }
  103. }
  104. static void find_path(list<node>& L, node_array<int>&  label,
  105.                                      node_array<node>& pred,
  106.                                      node_array<node>& mate,
  107.                                      node_array<edge>& bridge,
  108.                                      node x, node y)
  109. {
  110.   /* computes an even length alternating path from x to y begining with a 
  111.      matching edge (Tarjan: Data Structures and Network Algorithms, page 122)
  112.      Preconditions: 
  113.      a) x and y are even or shrinked
  114.      b) when x was made part of a blossom for the first time, y was a base 
  115.         and predecessor of the base of that blossom
  116.    */
  117.  if (x==y) 
  118.  { // [ x ]
  119.    L.append(x);
  120.    return;
  121.   }
  122.  if (label[x] == EVEN) 
  123.  { // [ x --> mate[x] --> path(pred[mate[x]],y) ]
  124.    find_path(L,label,pred,mate,bridge,pred[mate[x]],y);
  125.    L.push(mate[x]);
  126.    L.push(x);
  127.    return;
  128.  }
  129.  if (label[x] == ODD) 
  130.  { // [ x --> REV(path(source(bridge),mate[x])) --> path(target(bridge),y)) ]
  131.    node v;
  132.    list<node> L1;
  133.    find_path(L,label,pred,mate,bridge,target(bridge[x]),y);
  134.    find_path(L1,label,pred,mate,bridge,source(bridge[x]),mate[x]);
  135.    forall(v,L1) L.push(v);
  136.    L.push(x);
  137.    return;
  138.   }
  139. }
  140. list<edge> MAX_CARD_MATCHING(graph& G, int heur)
  141. float T = used_time();
  142.   // input: directed graph G, we make it undirected (symmetric) by inserting
  143.   //        reversal edges
  144.   list<edge> R;
  145.   int    strue = 0;
  146.   bool   done  = false;
  147.   node_array<int>  label(G,UNREACHED);
  148.   node_array<node> pred(G,nil);
  149.   node_array<int>  path1(G,0);
  150.   node_array<int>  path2(G,0);
  151.   node_array<edge> bridge(G,nil);
  152.   node_array<node> mate(G,nil);
  153.   // make graph symmetric
  154.   edge_array<edge> rev(G,nil);
  155.   compute_correspondence(G,rev);
  156.   edge e = G.first_edge();
  157.   while (e && rev[e]) e = G.succ_edge(e);
  158.   edge last_edge = nil;
  159.   if (e !=nil)
  160.   { last_edge = G.new_edge(target(e),source(e));
  161.     R.append(last_edge);
  162.     while (e != last_edge)
  163.     { if (rev[e] == nil)
  164.       { edge e1 = G.new_edge(target(e),source(e));
  165.         rev[e] = e1;
  166.         R.append(e1);
  167.         }
  168.       e = G.succ_edge(e);
  169.      }
  170.    }
  171.   edge_array<edge> reversal(G,nil);
  172.   for(e = G.first_edge(); e != last_edge; e = G.succ_edge(e))
  173.   { edge r = rev[e];
  174.     reversal[e] = r;
  175.     reversal[r] = e;
  176.    }
  177. /*
  178.   edge_array<edge> reversal(G,nil);
  179.   edge e = G.first_edge();
  180.   edge last_edge = G.last_edge();
  181.   do { edge e1 = G.new_edge(target(e),source(e));
  182.        reversal[e] = e1;
  183.        reversal[e1] = e;
  184.        R.append(e1);
  185.        e = G.succ_edge(e);
  186.       }
  187.   while(e != last_edge);
  188. */
  189.   switch (heur) {
  190.   case 1: { greedy(G,mate);
  191.             break;
  192.           }
  193.   case 2: { G.sort_nodes(cmp_degree);  // sort nodes by degree
  194.             heuristic(G,mate);
  195.             break;
  196.            }
  197.   }
  198.   while (! done)  /* main loop */
  199.   {
  200.     node_list Q;
  201.     node v;
  202.     node_partition base(G);    // now base(v) = v for all nodes v
  203.     done = true;
  204.    
  205.     forall_nodes(v,G)
  206.     { pred[v] = nil;
  207.   
  208.       if (mate[v] == nil)
  209.       { label[v] = EVEN; 
  210.         Q.append(v); 
  211.        }
  212.       else label[v] = UNREACHED;
  213.     }
  214.   
  215.     while (!Q.empty())    // search for augmenting path
  216.     {
  217.       node v = Q.pop();
  218.       edge e;
  219.       forall_adj_edges(e,v)
  220.       {
  221.         node w = G.target(e);
  222.         if (v == w) continue;    // ignore self-loops
  223.         if (base(v) == base(w) || (label[w] == ODD && base(w) == w)) 
  224.         continue;   // do nothing
  225.         if (label[w] == UNREACHED)
  226.         { label[w] = ODD;
  227.           pred[w] = v;
  228.           label[mate[w]] = EVEN;
  229.           Q.append(mate[w]);
  230.          }
  231.         else  // base(v) != base(w) && (label[w] == EVEN || base(w) !=w)
  232.         { 
  233.           node hv = base(v);
  234.           node hw = base(w);
  235.   
  236.           strue++;
  237.           path1[hv] = path2[hw] = strue;
  238.   
  239.           while ((path1[hw] != strue && path2[hv] != strue) &&
  240.                  (mate[hv] != nil || mate[hw] != nil) )
  241.           {
  242.             if (mate[hv] != nil)
  243.             { hv = base(pred[mate[hv]]);
  244.               path1[hv] = strue;
  245.              }
  246.   
  247.             if (mate[hw] != nil)
  248.             { hw = base(pred[mate[hw]]);
  249.               path2[hw] = strue;
  250.              }
  251.            }
  252.   
  253.           if (path1[hw] == strue || path2[hv] == strue)  // Shrink Blossom
  254.           { node x;
  255.             node y;
  256.             node b = (path1[hw] == strue) ? hw : hv;    // Base
  257. #if defined(REPORT_BLOSSOMS)
  258.   cout << "SHRINK BLOSSOMn";
  259.   cout << "bridge = "; 
  260.   G.print_edge(e);
  261.   newline;
  262.   cout << "base   = "; 
  263.   G.print_node(b);
  264.   newline;
  265.   cout << "path1  = ";
  266. #endif
  267.             x = base(v);
  268.             while (x != b)
  269.             { 
  270. #if defined(REPORT_BLOSSOMS)
  271.   G.print_node(x); 
  272.   cout << " ";
  273. #endif
  274.               base.union_blocks(x,b);
  275.               base.make_rep(b);
  276.               x = mate[x];
  277. #if defined(REPORT_BLOSSOMS)
  278.   G.print_node(x); 
  279.   cout << " ";
  280. #endif
  281.               y = base(pred[x]);
  282.               base.union_blocks(x,b);
  283.               base.make_rep(b);
  284.               Q.append(x);
  285.               bridge[x] = e;
  286.               x = y;
  287.              }
  288. #if defined(REPORT_BLOSSOMS)
  289.   G.print_node(b);
  290.   newline;
  291.   cout << "path2  = ";
  292. #endif
  293.             x = base(w);
  294.             while (x != b)
  295.             { 
  296. #if defined(REPORT_BLOSSOMS)
  297.   G.print_node(x); 
  298.   cout << " ";
  299. #endif
  300.               base.union_blocks(x,b);
  301.               base.make_rep(b);
  302.               x = mate[x];
  303. #if defined(REPORT_BLOSSOMS)
  304.   G.print_node(x); 
  305.   cout << " ";
  306. #endif
  307.               y = base(pred[x]);
  308.               base.union_blocks(x,b);
  309.               base.make_rep(b);
  310.               Q.append(x);
  311.               bridge[x] = reversal[e];
  312.               x = y;
  313.              }
  314. #if defined(REPORT_BLOSSOMS)
  315.   G.print_node(b);
  316.   newline;
  317.   newline;
  318. #endif
  319.           }
  320.           else  // augment path
  321.           {
  322.             list<node> P0,P1;
  323.             find_path(P0,label,pred,mate,bridge,v,hv);
  324.             P0.push(w);
  325.             find_path(P1,label,pred,mate,bridge,w,hw);
  326.             P1.pop();
  327.             while(! P0.empty())
  328.              { node a = P0.pop();
  329.                node b = P0.pop();
  330.                mate[a] = b;
  331.                mate[b] = a;
  332.               }
  333.             while(! P1.empty())
  334.              { node a = P1.pop();
  335.                node b = P1.pop();
  336.                mate[a] = b;
  337.                mate[b] = a;
  338.               }
  339.              Q.clear();                /* stop search (while Q not empty) */
  340.              done = false;             /* continue main loop              */
  341.              G.init_adj_iterator(v);
  342.              break;                    /* forall_adj_edges(e,v) ...       */
  343.            }
  344.         } // base(v) != base(w) && (label[w] == EVEN || base(w) !=w)
  345.   
  346.       } // for all adjacent edges
  347.   
  348.     } // while Q not empty
  349.   } // while not done
  350.  // restore graph (only original edges in result!)
  351.  forall(e,R) G.del_edge(e);  
  352.  list<edge> result;
  353. /*
  354.   node v;
  355.   forall_nodes(v,G)
  356.     if (mate[v] != nil)
  357.     { edge e;
  358.       forall_adj_edges(e,v)
  359.         if (mate[target(e)] == v) 
  360.         { result.append(e);
  361.           break;
  362.          }
  363.      }
  364. */
  365.  forall_edges(e,G) 
  366.  { node v = source(e);
  367.    node w = target(e);
  368.    if ( v != w  &&  mate[v] == w ) 
  369.    { result.append(e);
  370.      mate[v] = v;
  371.      mate[w] = w;
  372.     }
  373.   }
  374.  return result;
  375. }