00001 #include <stdlib.h>
00002 #include <stdio.h>
00003 #include "graph.h"
00004
00005
00006 #define NO_MEM fprintf(stderr,"Unable to allocate memory\n")
00007 #define LEPS 1e-8
00008
00009
00010
00011 float user_time ();
00012 BOOL ghc_tree (graph *);
00013
00014
00015 void print_time (float t)
00016 {
00017 long t_sec, t_hun;
00018 float t1;
00019
00020 if (t < 1.0)
00021 printf ("0'%d [s'10ms]\n", (long) (t * 100.0));
00022 else
00023 { t1 = t * 100.0;
00024 t_sec = (long) t;
00025 t_hun = (long) t1 - (long) 100 * t_sec;
00026 printf ("%d'%d [s'10ms]\n", t_sec, t_hun);
00027 }
00028 }
00029
00030
00031 BOOL alloc_graph (long n, long m, graph **gr)
00032 {
00033 if ((*gr = (graph *) malloc (sizeof (graph))) == (graph *) 0)
00034 return (FALSE);
00035 if (((*gr)->nodes = (node *) malloc (n * sizeof (node)))
00036 == (node *) 0)
00037 { free (*gr);
00038 return (FALSE);
00039 }
00040 if (((*gr)->edges = (edge *) malloc (2L * m * sizeof (edge)))
00041 == (edge *) 0)
00042 { free (*gr);
00043 free ((*gr)->nodes);
00044 return (FALSE);
00045 }
00046 return (TRUE);
00047 }
00048
00049
00050 void dealloc_graph (graph *gr)
00051 {
00052 free (gr->nodes);
00053 free (gr->edges);
00054 free (gr);
00055 }
00056
00057
00058 char skip_comment (FILE *fd)
00059 {
00060 char any;
00061 char *c;
00062 static char buf[256];
00063
00064 do { c = fgets (buf, 256, fd);
00065 fscanf (fd, "%c", &any);
00066 }
00067 while (any == 'c');
00068 return (any);
00069 }
00070
00071
00072 graph *get_graph (FILE *fd)
00073 {
00074 long n, m, m0, i, j, nod1, nod2;
00075 double cap;
00076 node *nptr, *nptr1, *nptr2;
00077 edge *eptr1, *eptr2;
00078 graph *gr;
00079 char inp[4], any;
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 fscanf (fd, "%c", &any);
00094 if (any == 'c')
00095 any = skip_comment (fd);
00096 if (any != 'p')
00097 { fprintf (stderr, "Problem line missing in input file\n");
00098 exit (1);
00099 }
00100 fscanf (fd, "%s", inp);
00101 if (inp[0] != 'g' || inp[1] != 'h' ||
00102 inp[2] != 'c' || inp[3] != 't' )
00103 { fprintf (stderr,
00104 "problem in input file is not Gomory/Gu cut tree\n");
00105 return ((graph *) 0);
00106 }
00107
00108 fscanf (fd, "%ld", &n);
00109 fscanf (fd, "%ld", &m);
00110
00111 if (! alloc_graph (n, m, &gr))
00112 { NO_MEM;
00113 return ((graph *) 0);
00114 }
00115
00116 gr->n_nodes = n;
00117 gr->n_edges0 = m;
00118 m0 = 0;
00119
00120
00121
00122 for (i = n, nptr = &(gr->nodes[n-1]); i > 0L; --nptr, --i)
00123 { nptr->id = i;
00124 nptr->first_edge = NILE;
00125 }
00126
00127 eptr1 = &(gr->edges[0L]);
00128 eptr2 = &(gr->edges[m]);
00129 for (j = 0L; j < m; j++)
00130 { if (fscanf (fd, "%s %ld %ld %lg", inp, &nod1, &nod2, &cap)
00131 == EOF)
00132 { fprintf (stderr,
00133 "EOF reached in input file, %d edges read\n", j);
00134 dealloc_graph (gr);
00135 return ((graph *) 0);
00136 }
00137 if (inp[0] != 'e')
00138 { printf ("syntax error - edge descriptor line expected\n");
00139 dealloc_graph (gr);
00140 return ((graph *) 0);
00141 }
00142 if (nod1 < 1 || nod1 > n)
00143 { fprintf (stderr,
00144 "invalid node id %d in input graph\n", nod1);
00145 dealloc_graph (gr);
00146 return ((graph *) 0);
00147 }
00148 if (nod2 < 1 || nod2 > n)
00149 { fprintf (stderr,
00150 "invalid node id %d in input graph\n", nod2);
00151 dealloc_graph (gr);
00152 return ((graph *) 0);
00153 }
00154 if (nod1 == nod2)
00155 { fprintf (stderr,
00156 "loop on node %d in input graph\n", nod1);
00157 dealloc_graph (gr);
00158 return ((graph *) 0);
00159 }
00160 if (cap > EPS)
00161 {
00162 --nod1;
00163 --nod2;
00164 nptr1 = &(gr->nodes[nod1]);
00165 nptr2 = &(gr->nodes[nod2]);
00166 eptr1->adjac = nptr2;
00167 eptr2->adjac = nptr1;
00168 eptr1->cap = cap;
00169 eptr2->cap = cap;
00170 eptr1->back = eptr2;
00171 eptr2->back = eptr1;
00172 if (nptr1->first_edge == NILE)
00173 { nptr1->first_edge = eptr1;
00174 eptr1->next = NILE;
00175 }
00176 else
00177 { eptr1->next = nptr1->first_edge;
00178 nptr1->first_edge = eptr1;
00179 }
00180 if (nptr2->first_edge == NILE)
00181 { nptr2->first_edge = eptr2;
00182 eptr2->next = NILE;
00183 }
00184 else
00185 { eptr2->next = nptr2->first_edge;
00186 nptr2->first_edge = eptr2;
00187 }
00188 ++eptr1;
00189 ++eptr2;
00190 }
00191 else
00192 {
00193
00194 m0++;
00195 }
00196 gr->n_edges = m - m0;
00197 }
00198 return (gr);
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 void print_tree (graph *gr)
00220 {
00221 node *nptr;
00222
00223 printf ("Gomory/Hu cut tree:\n");
00224 printf ("root 1\n");
00225 for (nptr = &(gr->nodes[gr->n_nodes-1L]);
00226 nptr >= &(gr->nodes[1L]); nptr--)
00227 printf ("e %d %d %e\n",
00228 nptr->id, nptr->parent->id, nptr->mincap);
00229 }
00230
00231 void compute_tree (int n, int m, int* os, int* ot, double* oc, int* cts, int* ctt, double* ctc)
00232 {
00233 long m0, i, j, nod1, nod2;
00234 double cap;
00235 node *nptr, *nptr1, *nptr2;
00236 edge *eptr1, *eptr2;
00237 graph *gr;
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 if (! alloc_graph (n, m, &gr))
00252 { NO_MEM;
00253 exit(1);
00254 }
00255
00256 gr->n_nodes = n;
00257 gr->n_edges0 = m;
00258 m0 = 0;
00259
00260
00261
00262 for (i = n, nptr = &(gr->nodes[n-1]); i > 0; --nptr, --i)
00263 { nptr->id = i;
00264 nptr->first_edge = NILE;
00265 }
00266
00267 eptr1 = &(gr->edges[0L]);
00268 eptr2 = &(gr->edges[m]);
00269
00270
00271 for (j = 0; j < m; j++)
00272 {
00273 nod1 = os[j];
00274 nod2 = ot[j];
00275 cap = oc[j];
00276 if (nod1 == nod2)
00277 { fprintf (stderr,
00278 "loop on node %d in input graph\n", nod1);
00279 dealloc_graph (gr);
00280 exit(1);
00281 }
00282 if (cap > EPS)
00283 {
00284 --nod1;
00285 --nod2;
00286 nptr1 = &(gr->nodes[nod1]);
00287 nptr2 = &(gr->nodes[nod2]);
00288 eptr1->adjac = nptr2;
00289 eptr2->adjac = nptr1;
00290 eptr1->cap = cap;
00291 eptr2->cap = cap;
00292 eptr1->back = eptr2;
00293 eptr2->back = eptr1;
00294 if (nptr1->first_edge == NILE)
00295 { nptr1->first_edge = eptr1;
00296 eptr1->next = NILE;
00297 }
00298 else
00299 { eptr1->next = nptr1->first_edge;
00300 nptr1->first_edge = eptr1;
00301 }
00302 if (nptr2->first_edge == NILE)
00303 { nptr2->first_edge = eptr2;
00304 eptr2->next = NILE;
00305 }
00306 else
00307 { eptr2->next = nptr2->first_edge;
00308 nptr2->first_edge = eptr2;
00309 }
00310 ++eptr1;
00311 ++eptr2;
00312 }
00313 else
00314 {
00315
00316 m0++;
00317 }
00318 gr->n_edges = m - m0;
00319 }
00320
00321
00322 ghc_tree (gr);
00323
00324
00325 int oi = 0;
00326
00327 for (nptr = &(gr->nodes[gr->n_nodes-1L]);
00328 nptr >= &(gr->nodes[1L]); nptr--) {
00329 cts[oi] = nptr->id;
00330 ctt[oi] = nptr->parent->id;
00331 ctc[oi] = nptr->mincap;
00332 oi++;
00333 }
00334 dealloc_graph(gr);
00335
00336 if( oi != n-1 ) {
00337 printf("Wrong number of edges in cut tree!\n");
00338 exit(1);
00339 }
00340
00341 return;
00342 }
00343
00344
00345 #ifdef GCT_MAIN
00346 void main (argc, argv)
00347 int argc;
00348 char **argv;
00349 {
00350 FILE *fd;
00351 graph *gr;
00352 long n1, n2;
00353 float t0, t1, t2;
00354
00355
00356
00357
00358
00359
00360
00361 if (argc != 2)
00362 { fprintf (stderr, "ghc_tree: call parameter missing\n");
00363 fprintf (stderr,
00364 "usage: ghc_tree <input filename>\n");
00365 exit (1);
00366 }
00367 t0 = user_time ();
00368 if ((fd = fopen (argv[1], "r")) == NULL)
00369 { fprintf(stderr, "Unable to open %s\n", argv[1]);
00370 exit (1);
00371 }
00372
00373 gr = get_graph (fd);
00374 if (gr == (graph *) 0)
00375 { close (fd);
00376 exit (1);
00377 }
00378 close (fd);
00379
00380 t1 = user_time ();
00381
00382 if (ghc_tree (gr))
00383 { t2 = user_time ();
00384 print_tree (gr);
00385 printf ("File input and initialization time: ");
00386 print_time (t1 - t0);
00387 printf ("Total execution time: ");
00388 print_time (t2 - t0);
00389 }
00390 dealloc_graph (gr);
00391 }
00392 #endif