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

  1. /*******************************************************************************
  2. +
  3. +  LEDA  2.1.1                                                 11-15-1991
  4. +
  5. +
  6. +  _planar.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. *                                                                              *
  18. *  PLANAR  (planarity test)                                                    *
  19. *                                                                              *
  20. *******************************************************************************/
  21.  
  22.  
  23. #include <LEDA/graph_alg.h>
  24. #include <LEDA/node_set.h>
  25. #include <LEDA/array.h>
  26.  
  27. declare(list,int)
  28.  
  29. struct edge_info
  30. {
  31.  edge e;
  32.  char plaz;
  33.  int  seg_nr;
  34.  int  block_nr;
  35.  
  36. OPERATOR_NEW(4)
  37. OPERATOR_DEL(4)
  38.  
  39. };
  40.  
  41.  
  42. struct block 
  43. {
  44.  list(int) L;
  45.  list(int) R;
  46.  
  47. OPERATOR_NEW(10)
  48. OPERATOR_DEL(10)
  49.  
  50. };
  51.  
  52.  
  53. typedef edge_info* ed_inf;
  54. typedef block* blptr;
  55.  
  56. declare(list,ed_inf)
  57. declare(list,blptr)
  58.  
  59. typedef list(ed_inf)* lsthead;
  60.  
  61. declare(array,lsthead)
  62. declare(array,node)
  63.  
  64. void swap_plaz( ed_inf& p )
  65. {
  66.  switch( p->plaz )
  67.       {
  68.        case 'L' : p->plaz = 'R'; break;
  69.        case 'R' : p->plaz = 'L'; break;
  70.        case '=' : p->plaz = '!'; break;
  71.        case '!' : p->plaz = '='; break;
  72.       }
  73. }
  74.  
  75.  
  76.  
  77. void mirror( array(lsthead)& segment, int s_nr)
  78. {
  79. int i = 1;
  80. ed_inf x;
  81.  
  82.  
  83.    forall( x, *(segment[s_nr])) 
  84.       if( i++ == 1 )
  85.          swap_plaz( x );
  86.       else if( x->seg_nr > s_nr )
  87.              mirror(segment, x->seg_nr);
  88.  
  89. }
  90.  
  91.  
  92.  
  93.  
  94. void flipping( array(lsthead)& segment, int s_nr, int h)
  95. {
  96. ed_inf x;
  97.    
  98.      forall( x, *(segment[s_nr]))
  99.       { 
  100.         if( x->block_nr == h )
  101.           {
  102.            swap_plaz( x );
  103.            if( x->seg_nr > s_nr )
  104.              mirror(segment, x->seg_nr );
  105.           }
  106.        }
  107.  
  108. }
  109.  
  110.  
  111. void null_block( lsthead& s, int h)
  112. {
  113. ed_inf x;
  114.    
  115.     forall( x, *s)
  116.       if( x->block_nr == h )
  117.            x->block_nr = 0;
  118.  
  119. }
  120.  
  121.  
  122. void upd_block_ctr( lsthead& s, int h)
  123. {
  124. ed_inf x;
  125.    
  126.     forall( x, *s)
  127.       if( x->block_nr > h )
  128.            x->block_nr = h;
  129.  
  130. }
  131.  
  132.  
  133.  
  134.  
  135. void init_segm( array(lsthead)& segment, int cur_nr, edge e)
  136. {
  137. ed_inf neu = new edge_info;
  138.  
  139.    neu->e = e;
  140.    neu->block_nr = 0;
  141.    neu->seg_nr = cur_nr;
  142.    neu->plaz = 'L';
  143.  
  144.    (*segment[cur_nr]).push(neu);
  145. }
  146.  
  147. void add_edge( lsthead& s, int s_nr, int h, edge e)
  148. {
  149. ed_inf neu = new edge_info;
  150.  
  151.    neu->e = e;
  152.    neu->block_nr = h;
  153.    neu->seg_nr = s_nr;
  154.    neu->plaz = '=';
  155.  
  156.    (*s).append(neu);
  157. }
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164. int max_L_R(blptr& top)
  165. {
  166. int lmax, rmax;
  167.  
  168.  lmax = rmax = 0;
  169.  
  170.  if( !(top->L).empty() )
  171.     lmax = (top->L).head();
  172.  if(!(top->R).empty() )
  173.     rmax = (top->R).head();
  174.  
  175.  return( Max(lmax,rmax) );
  176. }
  177.  
  178.  
  179.  
  180.  
  181. void swap_at(blptr& top)
  182. {
  183. list(int) tmp = top->L;
  184.  
  185.       top->L = top->R;
  186.       top->R = tmp;
  187. }
  188.  
  189.  
  190. int bipartite_test(list(blptr)& atblock, list(int)& A, int k,
  191.                     array(lsthead)& segment, int seg_nr)
  192. {
  193. int min_att;
  194. list_item top = atblock.first();
  195.  
  196.    min_att = A.tail();
  197.    while( top && max_L_R(atblock[top]) > min_att )
  198.     {
  199.      if( !atblock[top]->L.empty() && atblock[top]->L.head() > min_att )
  200.         {
  201.          //printf("vor swap %d %d %d\n",atblock[top]->L.head(),k,seg_nr);
  202.            flipping(segment, seg_nr, k-1 );
  203.            swap_at( atblock[top] );
  204.            if( !atblock[top]->L.empty() && atblock[top]->L.head() > min_att )
  205.                  return( -1 );
  206.         }
  207.      k--;
  208.      top = atblock.succ(top);
  209.     }
  210.  return( k-1 );
  211. }
  212.  
  213.  
  214.  
  215.  
  216. void update_block_stack(list(blptr)& atblock, int h,int dist,
  217.                         list(int)& A)
  218. {
  219.  
  220. int i;
  221.  
  222. list(int) ALB, ARB;
  223.  
  224.   for(i=h; i > dist; i--)
  225.    { list_item j = atblock.first();
  226.      ALB = ALB + ((atblock[j])->L);
  227.      ARB = ARB + ((atblock[j])->R);
  228.      atblock.pop();
  229.     }
  230.   blptr neu = new  block;  
  231.   neu->L = (A + ALB);
  232.   neu->R = ARB;
  233.   atblock.push(neu);
  234. }
  235.  
  236. void remove_node_below(int j,int sp_start,int wr,
  237.                        list(blptr)& atblock, lsthead& s)
  238. {
  239. int h;
  240.  if( j == sp_start)
  241.      j = wr;
  242.  else --j;
  243.  
  244.  list_item top = atblock.first();
  245.  
  246.  while(  top && ( !(atblock[top]->L).empty() && atblock[top]->L.head() == j 
  247.          ||    !(atblock[top]->R).empty() && atblock[top]->R.head() == j ) )
  248.    {
  249.     if( !(atblock[top]->L).empty() && atblock[top]->L.head() == j)
  250.         atblock[top]->L.pop();
  251.       
  252.     if( !(atblock[top]->R).empty() && atblock[top]->R.head() == j)
  253.         atblock[top]->R.pop();
  254.  
  255.     if( atblock[top]->L.empty() && atblock[top]->R.empty() )
  256.        {
  257.         h = atblock.length();
  258.         atblock.pop();
  259.         top = atblock.first();
  260.         null_block( s, h);
  261.        }
  262.         
  263.    }
  264.  
  265. }
  266.  
  267.  
  268. int strongly_planar(list(blptr)& atblock, int w0, list(int)& A,
  269.                     array(lsthead)& segment, int seg_nr)
  270. {
  271. int h;
  272.  A.clear();
  273.  
  274.  h = atblock.length();
  275.  while ( !atblock.empty())
  276.   {
  277.    list_item top = atblock.first();
  278.    if(  !atblock[top]->R.empty() && atblock[top]->R.head() > w0 )
  279.      {
  280.       swap_at( atblock[top] );
  281.       flipping(segment, seg_nr, h);
  282.       if( !atblock[top]->R.empty() && atblock[top]->R.head() > w0 )
  283.            return( false );
  284.      }
  285.    
  286.     A = A + atblock[top]->L + atblock[top]->R;
  287.     atblock.pop();
  288.     h--;
  289.   }
  290.  
  291.     A += w0;
  292.     return( true );
  293.  
  294. }
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302. list(int) plantest(array(node)& Graph_order, 
  303.                    node_array(int)& Dfsnr, edge e,
  304.                    array(lsthead)& segment, int& seg_nr)
  305. {
  306. int i,j, wr = 0, w0, h, dist, sp_start, sp_end, start_nr, cur_nr;
  307. node v, w, spine_node;
  308. edge seg_start;
  309.  
  310. list(int) A;
  311. list(blptr) atblock;
  312.  
  313.   spine_node = target(e);  // target(e) ist 1. Knoten des Spines zu S(e) 
  314.  
  315.   sp_start = Dfsnr[spine_node];
  316.  
  317.   if( sp_start > 1 )  // wr ist der Knoten, an dem S(e) den Stamm verlaesst
  318.      wr = Dfsnr[source(e)];
  319.  
  320.   // finde den Spine: laufe ueber T-Kanten bis zur 1. B-Kante
  321.  
  322.   forall_adj_edges(e,spine_node)
  323.      if( Dfsnr[target(e)] > Dfsnr[spine_node] ) // e ist T-Kante 
  324.         spine_node = target(e);
  325.      else break;
  326.  
  327.   sp_end = Dfsnr[source(e)]; // e ist die Basiskante von S(e)
  328.   w0 = Dfsnr[target(e)];     // w0 ist die Basisbefestigung am Stamm
  329.   cur_nr = seg_nr;
  330.    init_segm( segment, cur_nr, e);
  331.  
  332.  
  333.   for(j = sp_end; j >= sp_start; j--)
  334.    {
  335.      v = Graph_order[j]; // v ist der Knoten mit dfsnum j
  336.      
  337.      i = 1;
  338.      forall_adj_edges(seg_start,v) // betr. alle v verlassenden Kanten ausser
  339.                                    // der ersten Kante 
  340.       {
  341.        start_nr = cur_nr;
  342.        if( i++ > 1)
  343.        {
  344.         w = target(seg_start);
  345.  
  346.         if( Dfsnr[w] > Dfsnr[v] )  // Segment startet mit T-Kante 
  347.          { // teste S(seg_start)
  348.            start_nr = ++seg_nr;
  349.  
  350.            A = plantest(Graph_order, Dfsnr, seg_start, segment, seg_nr);
  351.  
  352.            if( A.empty() )
  353.                return( A );  // wenn A leer: nicht planar
  354.          }
  355.         else
  356.             A = Dfsnr[w]; // Segment besteht nur aus einer B-Kante 
  357.  
  358.         h = atblock.length(); // Anzahl der Eintraege im Blockstack
  359.         // teste, ob Graph noch bipartit, dist liefert Anzahl der zu
  360.         // verschraenkenden Bloecke
  361.  
  362.         if((dist=bipartite_test(atblock,A,h+1,segment,cur_nr)) == -1 )
  363.         { A.clear();
  364.           return( A ); 
  365.          }
  366.  
  367.      /* aktualisiere die Liste der Bloecke, evtl. werden Bloecke mit
  368.         der Liste A zu einem neuen Block verschmolzen */
  369.  
  370.         update_block_stack(atblock, h, dist, A);
  371.  
  372.         h = atblock.length(); // Anzahl der Eintraege im Blockstack
  373.  
  374.         upd_block_ctr(segment[cur_nr], h);
  375.  
  376.         add_edge(segment[cur_nr],start_nr,h,seg_start);
  377.        }
  378.       }
  379.     /* alle wj verlassenden Kanten sind betrachtet, entferne nun
  380.        alle Befestigungen parent( wj ) */
  381.  
  382.     remove_node_below(j,sp_start, wr, atblock,segment[cur_nr]);
  383.    }
  384.  
  385.    /* teste, ob S(e) stark planar */
  386.   if( ! strongly_planar(atblock, w0, A,segment,cur_nr))
  387.            A.clear();
  388.  
  389. null_block(segment[cur_nr],1);
  390.  
  391. //forall(k,A)
  392.   //printf("%d ",k);
  393.  //getchar();
  394.   return ( A );  // liefere Liste der Attachments ab
  395.  
  396. }
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405. int edge_cost(int vnum, int wnum, int l1, int l2)
  406. {
  407.   if( wnum < vnum )
  408.      return( 2*wnum );
  409.   else if ( l2 >= vnum)
  410.         return( 2*l1 );
  411.        else return ( 2*l1 + 1 );
  412. }
  413.  
  414. void bucket_s ( graph& G, int node_anz,
  415.                 node_array(int)& Dfsnr,
  416.                 node_array(int)& low1, 
  417.                 node_array(int)& low2 )
  418. {
  419.  node v,w;
  420. list(edge)* bucket = new list(edge) [2*node_anz + 1];
  421.  edge e;
  422.  int j, cost_ind;
  423.  
  424.  forall_nodes(v,G)
  425.   {
  426.    forall_adj_edges(e,v)
  427.     {
  428.       w = target(e);
  429.       cost_ind = edge_cost(Dfsnr[v],Dfsnr[w],low1[w],low2[w]);
  430.       bucket[cost_ind].push(e);
  431.     }
  432.   }
  433.  G.del_all_edges();
  434.  for(j=1; j <= 2*node_anz; j++)
  435.    forall(e,bucket[j])
  436.     {
  437.      v = source(e);
  438.      w = target(e);
  439.      G.new_edge(v,w,0);
  440.     }
  441.  
  442. }
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453. void low(list(edge)& DEL, node v, node prep,
  454.          int& cur_nr, node_set& reached,node_array(int)& Dfsnr,
  455.          node_array(int)& low1, node_array(int)& low2)
  456. {
  457. node w;
  458. edge e;
  459. int tcan1, tcan2, bcan1, bcan2;
  460.  
  461.   Dfsnr[v] = ++ cur_nr;
  462.   tcan1 = tcan2 = bcan1 = bcan2 = Dfsnr[v];
  463.   reached.insert(v);
  464.   forall_adj_edges(e,v)
  465.     {
  466.      w = target(e);
  467.      if( !reached.member(w) )
  468.       {
  469.        low(DEL,w,v,cur_nr,reached,Dfsnr,low1,low2);
  470.        if( low1[w] < tcan1 )
  471.         {
  472.          tcan2 = tcan1;
  473.          tcan1 = low1[w];
  474.         }
  475.        else if( low1[w] < tcan2 )
  476.               tcan2 = low1[w];
  477.       }
  478.      else if(( Dfsnr[w] >= Dfsnr[v])  || w == prep ) 
  479.                DEL.append(e) ; 
  480.           else if( Dfsnr[w] < bcan1 )
  481.                  { bcan2=bcan1;
  482.                    bcan1 = Dfsnr[w];
  483.                  }
  484.                else if( Dfsnr[w] < bcan2)
  485.                      bcan2 = Dfsnr[w];
  486.      }
  487.  
  488.  
  489.   low1[v] = Min(tcan1,bcan1);
  490.   if( tcan1 == bcan1)
  491.       low2[v] = Min(tcan2,bcan2);
  492.   else if ( tcan1 < bcan1)
  493.          low2[v] = Min(bcan1,tcan2);
  494.        else low2[v] = Min(tcan1,bcan2);
  495.  
  496. }
  497.  
  498.  
  499. void lowstart(graph& G,node_array(int)& Dfsnr,node_array(int)& low1,
  500.           node_array(int)& low2)
  501. {
  502. node v;
  503. node_set reached(G);
  504. int cur_nr = 0;
  505. list(edge) DEL;
  506. edge e;
  507.  
  508. G.reset(); 
  509. forall_nodes(v,G)
  510.   {
  511.     if( !reached.member(v) )
  512.       low(DEL,v,v,cur_nr,reached,Dfsnr,low1,low2);
  513.   }
  514. G.reset();
  515.     forall(e,DEL)
  516.         G.del_edge(e);
  517. }
  518.  
  519.  
  520. void dfs( node v, 
  521.          int& cur_nr, node_set& reached,node_array(int)& Dfsnr)
  522. {
  523. node w;
  524.  
  525.   Dfsnr[v] = ++ cur_nr;
  526.   reached.insert(v);
  527.   forall_adj_nodes(w,v)
  528.      if( !reached.member(w) )
  529.        dfs(w,cur_nr,reached,Dfsnr);
  530.  
  531. }
  532.  
  533. void dfsstart(graph& G,node_array(int)& Dfsnr)
  534. {
  535. node v;
  536. node_set reached(G);
  537. int cur_nr = 0;
  538.  
  539. G.reset(); 
  540. forall_nodes(v,G)
  541.     if( !reached.member(v) )
  542.       dfs(v,cur_nr,reached,Dfsnr);
  543. G.reset();
  544. }
  545.  
  546.  
  547.  
  548. void cycl_embedding(graph& G,graph& Comb_Gr, array(node)& Comb_ord, array(node)& Graph_ord,
  549.                     node_array(int)& Dfsnr, node_array(int)& Comb_D_nr,
  550.                     edge_array(int)& alpha, edge e, edge& grenze)
  551. {
  552. node v, w, spine_node;
  553. edge active, x, seg_start, fst, Lcur, Rcur;
  554. list(edge) Comb_List, Gr_List;
  555. int i, j, k, wr, w0, sp_start, sp_end, pos;
  556.  
  557. if( source(e) != Graph_ord[0] )
  558.   wr = Dfsnr[source(e)];
  559. else wr = 0;
  560.  
  561. sp_start = Dfsnr[target(e)];
  562. pos = alpha[e];
  563. spine_node = target(e);
  564.  
  565. if( wr < sp_start )
  566. {
  567.   forall_adj_edges(e,spine_node)
  568.      if( Dfsnr[target(e)] > Dfsnr[spine_node] ) // e ist T-Kante 
  569.         spine_node = target(e);
  570.      else break;
  571. }  
  572.  
  573.   sp_end = Dfsnr[source(e)]; // e ist die Basiskante von S(e)
  574.   w0 = Dfsnr[target(e)];     // w0 ist die Basisbefestigung am Stamm
  575.  
  576. //printf(" wr %d start %d end %d w0 %d\n",wr,sp_start,sp_end,w0);
  577.  
  578.   for(i= sp_start; i > wr && i < sp_end; i++)
  579.     {
  580.      v = Comb_ord[i];
  581.      if( i > 1 )
  582.       {
  583.         if( i == sp_start )
  584.          w = Comb_ord[wr];
  585.         else w = Comb_ord[i-1];
  586.  
  587.         Comb_Gr.new_edge(v,w);
  588.       }
  589.  
  590.      Comb_Gr.new_edge(v,Comb_ord[i+1]);
  591.     }
  592.  
  593. //Comb_Gr.print();
  594. //getchar();
  595.    if( wr < sp_start )
  596.     {
  597.      if(sp_end == sp_start)
  598.        w = Comb_ord[wr];
  599.      else
  600.        w = Comb_ord[sp_end -1];
  601.  
  602.      Comb_Gr.new_edge(Comb_ord[sp_end], w);
  603.  
  604.      if( wr > 0 )
  605.      {
  606.         v = Comb_ord[wr];
  607.         if( pos == 'L')
  608.           {
  609.             fst = Comb_Gr.first_adj_edge(v);
  610.              Comb_Gr.new_edge(fst,Comb_ord[sp_start],0,after);
  611.           }
  612.         else Comb_Gr.new_edge(v,Comb_ord[sp_start]);
  613.      }
  614.    }
  615.  
  616.  
  617.      v = Comb_ord[sp_end];
  618.      if( pos == 'L')
  619.        {
  620.     fst = Comb_Gr.first_adj_edge(v);
  621.     Comb_Gr.new_edge(fst,Comb_ord[w0],0,after);
  622.        }
  623.      else Comb_Gr.new_edge(v,Comb_ord[w0]);
  624. //Comb_Gr.print();
  625. //getchar();
  626.        v = Comb_ord[w0];
  627.        Comb_List = Comb_Gr.adj_edges(v);
  628.  
  629.      if( wr > 0 )
  630.       {
  631.        w = Graph_ord[w0];
  632.        Gr_List = G.adj_edges(w);
  633.  
  634. //printf(" sg %d tg %d\n",Comb_D_nr[source(grenze)],Comb_D_nr[target(grenze)]);
  635.        k = 0;
  636.        forall(x, Gr_List)
  637.     if( Dfsnr[target(x)] > k && Dfsnr[target(x)] <= wr)
  638.           {  active = x; 
  639.                  k = Dfsnr[target(x)]; 
  640.               }
  641.        forall(x,Comb_List)
  642.          if(Comb_D_nr[target(x)] == Dfsnr[target(active)])
  643.           break;
  644.        active = x;
  645.       }
  646.      else active = Comb_List.head();
  647.  
  648. //printf(" sa %d ta %d\n",Comb_D_nr[source(active)],Comb_D_nr[target(active)]);
  649.      if( w0 != Comb_D_nr[source(grenze)] )
  650.        {
  651.         if( pos == 'L' )
  652.              x = Comb_Gr.new_edge(active,Comb_ord[sp_end],0,before);
  653.         else
  654.              x = Comb_Gr.new_edge(active,Comb_ord[sp_end],0,after);
  655.        }
  656.       else if ( pos == 'R' )
  657.              x = Comb_Gr.new_edge(grenze,Comb_ord[sp_end],0,before);
  658.            else
  659.                 x = Comb_Gr.new_edge(grenze,Comb_ord[sp_end],0,after);
  660.  
  661.       Lcur = Rcur = x;
  662.  
  663.  
  664.       if( wr < sp_start)
  665.          for(j = sp_end; j >= sp_start; j--)
  666.           {
  667.             v = Graph_ord[j];
  668.             i = 1;
  669.             forall_adj_edges(seg_start,v)
  670.               if( i++ > 1)
  671.                {
  672.                  if( alpha[seg_start] == 'L' ) 
  673.                   cycl_embedding(G,Comb_Gr,Comb_ord,Graph_ord,Dfsnr,Comb_D_nr,alpha,seg_start,Lcur);
  674.                  else
  675.                   cycl_embedding(G,Comb_Gr,Comb_ord,Graph_ord,Dfsnr,Comb_D_nr,alpha,seg_start,Rcur);
  676.                }
  677.            }
  678.  
  679.          if( pos == 'R' && Comb_D_nr[source(Rcur)] <= Comb_D_nr[source(grenze)] )
  680.                  grenze = Rcur;
  681.          else
  682.              if( pos == 'L' && Comb_D_nr[source(Lcur)] <= Comb_D_nr[source(grenze)] )
  683.                  grenze = Lcur;
  684.  
  685.  
  686. }   
  687.  
  688. /*
  689.   planar( G, Comb) testet den Graphen G auf Planaritaet und berechnet
  690.   die kombinatorische Einbettung von G. Der Graph mit den zyklischen
  691.   Adjazenzlisten wird in Comb zurueckgeliefert.
  692.   Eingabe G : gerichtete Version eines zweifach  zusammenhaengenden
  693.               ungerichteten Graphen.
  694.   
  695.   planar() liefert true, falls G planar, sonst false
  696. */
  697.  
  698.  
  699.  
  700. int PLANAR( graph& G)
  701. {
  702.  
  703.   error_handler(0,"PLANAR: sorry, not implemented in this version"); 
  704.   return false;
  705.  
  706.  
  707. int i, ed, n=0, seg_num = 0;
  708. char basis;
  709. list(int) A;
  710. node v, w, aux;
  711. edge e, add_ed, grenze;
  712. ed_inf x;
  713.  
  714. graph Comb_Gr;
  715.  
  716. /*
  717. G.insert_reverse_edges();
  718. eliminate_parallel_edges(G);
  719. */
  720.  
  721. node_array(int) Dfsnr(G),
  722.                 low1(G),
  723.                 low2(G);
  724.  
  725.  
  726. lowstart(G,Dfsnr,low1,low2);
  727.  
  728. n = G.number_of_nodes();
  729. ed = G.number_of_edges();
  730. if( ed > 3*n - 6 )
  731.   { //printf(" no of edges : %d  > %d (more than 3*n - 6 edges)\n",ed,3*n - 6);
  732.     return false;
  733.   }
  734.  
  735. G.reset();
  736. bucket_s(G,n,Dfsnr,low1,low2);
  737.  
  738. dfsstart(G,Dfsnr);
  739.  
  740. w = G.first_node();
  741. aux = G.new_node();
  742. add_ed = G.new_edge(aux,w);
  743.  
  744.  
  745. n++;
  746. array(lsthead) segment(n);
  747. for(i =0; i < n; i++)
  748.    segment[i] = new list(ed_inf);
  749.  
  750.  
  751. array(node) Graph_order(0,n);
  752. edge_array(int) alpha(G);
  753. alpha[add_ed] = 'L';
  754.  
  755.  
  756. forall_nodes(w,G)    
  757.   if (w != aux) 
  758.     Graph_order[Dfsnr[w]] = w;
  759.   else Graph_order[0] = aux;
  760.  
  761. A = plantest(Graph_order, Dfsnr, add_ed, segment, seg_num);
  762.  
  763. if( A.empty() )
  764.     return false;
  765.  
  766. for(i=0; i <= seg_num ; i++)
  767.     {
  768.       x = (*segment[i]).head();
  769.       basis = x->plaz;
  770.       forall(x, (*segment[i]) )
  771.          {
  772.            e = x->e;
  773.           if( basis == 'L' )
  774.              {
  775.               if ( x->plaz == 'L' || x->plaz == '=')
  776.                   alpha[e] = 'L';
  777.               else if( x->plaz == '!')
  778.                   alpha[e] = 'R';
  779.              }
  780.            else
  781.                if(x->plaz == 'R' || x->plaz == '=')
  782.                         alpha[e] = 'R';
  783.                else alpha[e] = 'L';
  784.          }
  785.      } 
  786.  
  787. list(node) G_Lst, Comb_Lst;
  788.  
  789. Comb_Gr = G;
  790. n = Comb_Gr.number_of_nodes();
  791. node_array(int) Comb_D_nr(Comb_Gr);
  792. array(node) Comb_ord(0,n);
  793.  
  794. G_Lst = G.all_nodes();
  795. Comb_Lst = Comb_Gr.all_nodes();
  796. list_item topg = G_Lst.first();
  797. list_item topn = Comb_Lst.first();
  798. while ( topg != G_Lst.last())
  799.   Comb_D_nr[Comb_Lst[topn]] = Dfsnr[G_Lst[topg]];
  800.   topg = G_Lst.succ(topg);
  801.   topn = Comb_Lst.succ(topn);
  802. }
  803. aux = Comb_Lst[topn];
  804.  
  805. forall_nodes(w,Comb_Gr)
  806.   if( w != aux )
  807.      Comb_ord[Comb_D_nr[w]] = w;
  808.   else Comb_ord[0] = aux;
  809.  
  810.  
  811.  
  812. v = Comb_ord[2];
  813. grenze = Comb_Gr.first_adj_edge(v);
  814.  
  815. Comb_Gr.del_all_edges();
  816.  
  817.  cycl_embedding(G,Comb_Gr,Comb_ord,Graph_order,Dfsnr,Comb_D_nr,alpha,add_ed,grenze);
  818.  
  819.  Comb_Gr.del_node( aux );
  820.  
  821. G = Comb_Gr;
  822.  
  823. return true;
  824.  
  825. }
  826.