home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************
- +
- + LEDA 2.1.1 11-15-1991
- +
- +
- + _trans_acyclic.c
- +
- +
- + Copyright (c) 1991 by Max-Planck-Institut fuer Informatik
- + Im Stadtwald, 6600 Saarbruecken, FRG
- + All rights reserved.
- +
- *******************************************************************************/
-
-
-
- #include <LEDA/graph_alg.h>
-
-
- typedef list(node)* nodelist_ptr;
-
- declare(node_array,list_item)
-
- /*
- #include <LEDA/array.h>
-
- declare(array,nodelist_ptr)
- declare(array,node)
- declare(array2,int)
- */
-
-
- void acyclic_transitive_closure(graph& G)
- { // computes transitive closure of acyclic graph G
-
- edgelist E1;
- node v,w;
-
- int i,j,k,h;
- int n = G.number_of_nodes();
-
- TOPSORT1(G);
-
- node_array(bool) marked(G);
- node_array(int) top_ord(G); // topologic order
-
- // array(nodelist_ptr) C(n+1); // chains C[1], C[2], ...
-
- nodelist_ptr* C = new nodelist_ptr[n+1];
-
- node_array(int) chain(G); // chain[v] = i iff v in C[i]
- node_array(list_item) chain_loc(G); // chain_loc[v]
- // = location of v in its chain
-
- /*
- array(node) N(n); // N[i] = node i (in topological order)
- array2(int) reach(n,n); // reach[h][i] = min { j ; N[j] in C[h] and
- // there is a path from N[i] to N[j] }
- */
-
- node* N = new node[n];
-
- int** reach = new int*[n];
- for(i=0; i<n; i++) reach[i] = new int[n];
-
-
- i=0;
- forall_nodes(v,G) { marked[v]=1; top_ord[v] = i; N[i]=v; i++; }
-
- //Kettenzerlegung C[0], C[1], ..., C[k]
-
- k=0;
- C[0] = new list(node);
- forall_nodes(v,G)
- { node v0 = v;
- if (marked[v0])
- { chain_loc[v0]=C[k]->append(v0);
- chain[v0]=k;
- while (v0)
- { forall_adj_nodes(w,v0) if (marked[w]) break;
- if (w) { marked[w]=0;
- chain[w]=k;
- chain_loc[w]=C[k]->append(w);
- }
- v0=w;
- }
- k++;
- C[k] = new list(node);
- }
- }
- k--;
-
-
- for(h=0; h<n; h++)
- for(i=0; i<n; i++)
- reach[h][i] = n+1;
-
- Forall_nodes(v,G) //decreasing order
- { i=top_ord[v];
- forall_adj_nodes(w,v) //increasing order
- { j=top_ord[w];
- if (j <= reach[chain[w]][j])
- for(h=0; h<=k; h++)
- if (reach[h][j] < reach[h][i]) reach[h][i] = reach[h][j];
- }
- reach[chain[v]][i] = i;
- }
-
-
- G.del_all_edges();
-
- forall_nodes(v,G)
- { for(i=0; i<=k; i++)
- if ((j=reach[i][top_ord[v]]) < n+1)
- { C[i]->set_iterator(C[i]->pred(chain_loc[N[j]]));
- while (C[i]->next_element(w)) G.new_edge(v,w);
- }
- }
-
- for(i=0; i<=k; i++) C[i]->clear();
-
- for(i=0; i<n; i++) delete reach[i];
-
- delete reach;
- delete C;
- delete N;
-
- }
-
-
-