home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / src / graph_al / _mc_matc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-15  |  7.9 KB  |  347 lines

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