00001 /* $Id: acyclic.c,v 1.2 2005/03/08 23:34:10 erg Exp $ $Revision: 1.2 $ */ 00002 /* vim:set shiftwidth=4 ts=8: */ 00003 00004 /********************************************************** 00005 * This software is part of the graphviz package * 00006 * http://www.graphviz.org/ * 00007 * * 00008 * Copyright (c) 1994-2004 AT&T Corp. * 00009 * and is licensed under the * 00010 * Common Public License, Version 1.0 * 00011 * by AT&T Corp. * 00012 * * 00013 * Information and Software Systems Research * 00014 * AT&T Research, Florham Park NJ * 00015 **********************************************************/ 00016 00017 00018 /* 00019 * Break cycles in a directed graph by depth-first search. 00020 */ 00021 00022 #include "dot.h" 00023 00024 void reverse_edge(edge_t * e) 00025 { 00026 edge_t *f; 00027 00028 delete_fast_edge(e); 00029 if ((f = find_fast_edge(e->head, e->tail))) 00030 merge_oneway(e, f); 00031 else 00032 virtual_edge(e->head, e->tail, e); 00033 } 00034 00035 static void 00036 dfs(node_t * n) 00037 { 00038 int i; 00039 edge_t *e; 00040 node_t *w; 00041 00042 if (ND_mark(n)) 00043 return; 00044 ND_mark(n) = TRUE; 00045 ND_onstack(n) = TRUE; 00046 for (i = 0; (e = ND_out(n).list[i]); i++) { 00047 w = e->head; 00048 if (ND_onstack(w)) { 00049 reverse_edge(e); 00050 i--; 00051 } else { 00052 if (ND_mark(w) == FALSE) 00053 dfs(w); 00054 } 00055 } 00056 ND_onstack(n) = FALSE; 00057 } 00058 00059 00060 void acyclic(graph_t * g) 00061 { 00062 int c; 00063 node_t *n; 00064 00065 for (c = 0; c < GD_comp(g).size; c++) { 00066 GD_nlist(g) = GD_comp(g).list[c]; 00067 for (n = GD_nlist(g); n; n = ND_next(n)) 00068 ND_mark(n) = FALSE; 00069 for (n = GD_nlist(g); n; n = ND_next(n)) 00070 dfs(n); 00071 } 00072 } 00073