00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "dot.h"
00027
00028
00029 static graph_t *G;
00030 static node_t *Last_node;
00031 static char Cmark;
00032
00033 static void
00034 begin_component(void)
00035 {
00036 Last_node = GD_nlist(G) = NULL;
00037 }
00038
00039 static void
00040 add_to_component(node_t * n)
00041 {
00042 GD_n_nodes(G)++;
00043 ND_mark(n) = Cmark;
00044 if (Last_node) {
00045 ND_prev(n) = Last_node;
00046 ND_next(Last_node) = n;
00047 } else {
00048 ND_prev(n) = NULL;
00049 GD_nlist(G) = n;
00050 }
00051 Last_node = n;
00052 ND_next(n) = NULL;
00053 }
00054
00055 static void
00056 end_component(void)
00057 {
00058 int i;
00059
00060 i = GD_comp(G).size++;
00061 GD_comp(G).list = ALLOC(GD_comp(G).size, GD_comp(G).list, node_t *);
00062 GD_comp(G).list[i] = GD_nlist(G);
00063 }
00064
00065 static void
00066 search_component(graph_t * g, node_t * n)
00067 {
00068 int c, i;
00069 elist vec[4];
00070 node_t *other;
00071 edge_t *e;
00072
00073 add_to_component(n);
00074 vec[0] = ND_out(n);
00075 vec[1] = ND_in(n);
00076 vec[2] = ND_flat_out(n);
00077 vec[3] = ND_flat_in(n);
00078
00079 for (c = 0; c <= 3; c++) {
00080 if (vec[c].list)
00081 for (i = 0; (e = vec[c].list[i]); i++) {
00082 if ((other = e->head) == n)
00083 other = e->tail;
00084 if ((ND_mark(other) != Cmark) && (other == UF_find(other)))
00085 search_component(g, other);
00086 }
00087 }
00088 }
00089
00090 void decompose(graph_t * g, int pass)
00091 {
00092 graph_t *subg;
00093 node_t *n, *v;
00094
00095 G = g;
00096 if (++Cmark == 0)
00097 Cmark = 1;
00098 GD_n_nodes(g) = GD_comp(g).size = 0;
00099 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00100 v = n;
00101 if ((pass > 0) && (subg = ND_clust(v)))
00102 v = GD_rankleader(subg)[ND_rank(v)];
00103 else if (v != UF_find(v))
00104 continue;
00105 if (ND_mark(v) != Cmark) {
00106 begin_component();
00107 search_component(g, v);
00108 end_component();
00109 }
00110 }
00111 }