bc_spanning.c

Go to the documentation of this file.
00001 #include "bc_spanning.h"
00002 
00003 #if 0
00004 int DPspanningMain (int ac,
00005                     char **av)
00006 {
00007   double wt;
00008   int rval = 0;
00009   int i,
00010     ncount,
00011     ecount;
00012   int *elist = (int *) NULL;
00013   double *wlist = (double *) NULL;
00014   int *tlist = (int *) NULL;
00015 
00016   if (ac < 2)
00017   {
00018     DPspanningUsage (*av);
00019     return 1;
00020   }
00021 
00022   rval = getprob (av[1], &ncount, &ecount, &elist, &wlist);
00023   if (rval)
00024   {
00025     fprintf (stderr, "getprob failed\n");
00026     goto CLEANUP;
00027   }
00028 
00029   tlist = (int *) malloc ((ncount - 1) * sizeof (int));
00030   if (!tlist)
00031   {
00032     fprintf (stderr, "out of memory for tlist\n");
00033     rval = 1;
00034     goto CLEANUP;
00035   }
00036 
00037   rval = kruskal_spanningtree (ncount, ecount, elist, wlist, tlist, 0);
00038   if (rval)
00039   {
00040     fprintf (stderr, "kruskal_spanningtree failed\n");
00041     goto CLEANUP;
00042   }
00043 
00044   wt = 0.0;
00045   for (i = 0; i < ncount - 1; i++)
00046     wt += wlist[tlist[i]];
00047 
00048   printf ("Tree Weight: %f\n", wt);
00049   fflush (stdout);
00050 
00051 CLEANUP:
00052 
00053   if (tlist)
00054     free (tlist);
00055   if (elist)
00056     free (elist);
00057   if (wlist)
00058     free (wlist);
00059   return rval;
00060 }
00061 #endif
00062 
00063 int biased_spanningtree (int ncount,
00064                          int ecount,
00065                          int *elist,
00066                          double *wlist,
00067                          int *tlist,
00068                          void *function_data)
00069 {
00070   DPedgeSet_t *eedges = (DPedgeSet_t *) function_data;
00071   int i,
00072     k,
00073     tcount = 0;
00074   DPspanningEdge *e;
00075   int *perm = (int *) NULL;
00076   DPspanningNode *nlist = (DPspanningNode *) NULL;
00077   DPspanningEdge *edglist = (DPspanningEdge *) NULL;
00078   int rval = 0;
00079   int nsedges = 0;
00080   int *nodemarks = 0;
00081 
00082   rval = buildgraph (ecount, elist, wlist, &edglist);
00083   function_data = 0;
00084   if (rval)
00085   {
00086     fprintf (stderr, "buildgraph failed\n");
00087     goto CLEANUP;
00088   }
00089 
00090   perm = (int *) malloc (ecount * sizeof (int));
00091   nodemarks = (int *) malloc (ncount * sizeof (int));
00092   if (!perm || !nodemarks)
00093   {
00094     fprintf (stderr, "out of memory for perm\n");
00095     rval = 1;
00096     goto CLEANUP;
00097   }
00098   memset (nodemarks, 0, sizeof (int) * ncount);
00099   for (i = 0; i < ecount; i++)
00100     perm[i] = i;
00101 
00102   /* here we put at the end some special edges */
00103   for (i = 0; i < eedges->nedges; i++)
00104   {
00105     nodemarks[eedges->edges[i * 2]] = 1;
00106     nodemarks[eedges->edges[i * 2 + 1]] = 1;
00107   }
00108   for (i = 1; i < ecount; i++)
00109   {
00110     if (nodemarks[edglist[perm[i]].ends[0]]
00111         || nodemarks[edglist[perm[i]].ends[1]])
00112     {
00113       SWAP (perm[i], perm[nsedges++], k);
00114     }
00115   }
00116   /* up to now the edges touching the 'marked' nodes are in the first 'nsedges' positions */
00117 
00118   qsort_DPspanningEdges (perm, edglist, nsedges, ecount - 1);
00119   qsort_DPspanningEdges (perm, edglist, 0, nsedges - 1);
00120 
00121   nlist = (DPspanningNode *) malloc (ncount * sizeof (DPspanningNode));
00122   if (!nlist)
00123   {
00124     fprintf (stderr, "out of memory for nlist\n");
00125     rval = 1;
00126     goto CLEANUP;
00127   }
00128   for (i = 0; i < ncount; i++)
00129   {
00130     makeset (&nlist[i]);
00131   }
00132 
00133   for (i = 0, k = ncount - 1; k > 0 && i < ecount; i++)
00134   {
00135     e = &edglist[perm[i]];
00136     if (find (&nlist[e->ends[0]]) != find (&nlist[e->ends[1]]))
00137     {
00138       slink (find (&nlist[e->ends[0]]), find (&nlist[e->ends[1]]));
00139       tlist[tcount++] = perm[i];
00140       k--;
00141     }
00142   }
00143 
00144   if (k)
00145   {
00146     fprintf (stderr, "Disconected graph\n");
00147     rval = 1;
00148   }
00149 
00150 CLEANUP:
00151 
00152   if (perm)
00153     free (perm);
00154   if (nlist)
00155     free (nlist);
00156   if (edglist)
00157     free (edglist);
00158   if (nodemarks)
00159     free (nodemarks);
00160 
00161   return rval;
00162 }
00163 
00164 int kruskal_spanningtree (int ncount,
00165                           int ecount,
00166                           int *elist,
00167                           double *wlist,
00168                           int *tlist,
00169                           void *function_data)
00170 {
00171   int i,
00172     k,
00173     tcount = 0;
00174   DPspanningEdge *e;
00175   int *perm = (int *) NULL;
00176   DPspanningNode *nlist = (DPspanningNode *) NULL;
00177   DPspanningEdge *edglist = (DPspanningEdge *) NULL;
00178   int rval = 0;
00179 
00180   rval = buildgraph (ecount, elist, wlist, &edglist);
00181   function_data = 0;
00182   if (rval)
00183   {
00184     fprintf (stderr, "buildgraph failed\n");
00185     goto CLEANUP;
00186   }
00187 
00188   perm = (int *) malloc (ecount * sizeof (int));
00189   if (!perm)
00190   {
00191     fprintf (stderr, "out of memory for perm\n");
00192     rval = 1;
00193     goto CLEANUP;
00194   }
00195   for (i = 0; i < ecount; i++)
00196     perm[i] = i;
00197 
00198   qsort_DPspanningEdges (perm, edglist, 0, ecount - 1);
00199 
00200   nlist = (DPspanningNode *) malloc (ncount * sizeof (DPspanningNode));
00201   if (!nlist)
00202   {
00203     fprintf (stderr, "out of memory for nlist\n");
00204     rval = 1;
00205     goto CLEANUP;
00206   }
00207   for (i = 0; i < ncount; i++)
00208   {
00209     makeset (&nlist[i]);
00210   }
00211 
00212   for (i = 0, k = ncount - 1; k > 0 && i < ecount; i++)
00213   {
00214     e = &edglist[perm[i]];
00215     if (find (&nlist[e->ends[0]]) != find (&nlist[e->ends[1]]))
00216     {
00217       slink (find (&nlist[e->ends[0]]), find (&nlist[e->ends[1]]));
00218       tlist[tcount++] = perm[i];
00219       k--;
00220     }
00221   }
00222 
00223   if (k)
00224   {
00225     fprintf (stderr, "Disconected graph\n");
00226     rval = 1;
00227   }
00228 
00229 CLEANUP:
00230 
00231   if (perm)
00232     free (perm);
00233   if (nlist)
00234     free (nlist);
00235   if (edglist)
00236     free (edglist);
00237 
00238   return rval;
00239 }
00240 
00241 /* qsort from J. Bentley (unix review, march '92)  */
00242 
00243 void qsort_DPspanningEdges (int *perm,
00244                             DPspanningEdge * elist,
00245                             int l,
00246                             int u)
00247 {
00248   int i,
00249     j;
00250   int itemp;
00251   double t;
00252 
00253   if (l >= u)
00254     return;
00255 
00256   SWAP (perm[l], perm[(l + u) / 2], itemp);
00257 
00258   i = l;
00259   j = u + 1;
00260   t = elist[perm[l]].weight;
00261 
00262   while (1)
00263   {
00264     do
00265       i++;
00266     while (i <= u && elist[perm[i]].weight > t);
00267     do
00268       j--;
00269     while (elist[perm[j]].weight < t);
00270     if (j < i)
00271       break;
00272     SWAP (perm[i], perm[j], itemp);
00273   }
00274   SWAP (perm[l], perm[j], itemp);
00275   qsort_DPspanningEdges (perm, elist, l, j - 1);
00276   qsort_DPspanningEdges (perm, elist, i, u);
00277 }
00278 
00279 void printtree (int ncount,
00280                 int *elist,
00281                 int *tlist)
00282 {
00283   int i,
00284     p;
00285 
00286   printf ("%d %d\n", ncount, ncount - 1);
00287   for (i = 0; i < ncount - 1; i++)
00288   {
00289     p = tlist[i];
00290     printf ("%d %d 1\n", elist[2 * p], elist[2 * p + 1]);
00291   }
00292 }
00293 
00294 int getprob (char *fname,
00295              int *p_ncount,
00296              int *p_ecount,
00297              int **p_elist,
00298              double **p_wlist)
00299 {
00300   FILE *f = (FILE *) NULL;
00301   int i,
00302     end1,
00303     end2;
00304   double w;
00305   int rval = 0;
00306   int ncount,
00307     ecount;
00308   double *wlist = (double *) NULL;
00309   int *elist = (int *) NULL;
00310 
00311   if ((f = fopen (fname, "r")) == NULL)
00312   {
00313     fprintf (stderr, "Unable to open %s for input\n", fname);
00314     rval = 1;
00315     goto CLEANUP;
00316   }
00317 
00318   if (fscanf (f, "%d %d", &ncount, &ecount) != 2)
00319   {
00320     fprintf (stderr, "Input file %s has invalid format\n", fname);
00321     rval = 1;
00322     goto CLEANUP;
00323   }
00324 
00325   printf ("Nodes: %d  Edges: %d\n", ncount, ecount);
00326   fflush (stdout);
00327 
00328   elist = (int *) malloc (2 * ecount * sizeof (int));
00329   if (!elist)
00330   {
00331     fprintf (stderr, "out of memory for elist\n");
00332     rval = 1;
00333     goto CLEANUP;
00334   }
00335 
00336   wlist = (double *) malloc (ecount * sizeof (double));
00337   if (!wlist)
00338   {
00339     fprintf (stderr, "out of memory for wlist\n");
00340     rval = 1;
00341     goto CLEANUP;
00342   }
00343 
00344   for (i = 0; i < ecount; i++)
00345   {
00346     if (fscanf (f, "%d %d %lf", &end1, &end2, &w) != 3)
00347     {
00348       fprintf (stderr, "%s has invalid input format\n", fname);
00349       rval = 1;
00350       goto CLEANUP;
00351     }
00352     elist[2 * i] = end1;
00353     elist[2 * i + 1] = end2;
00354     wlist[i] = w;
00355   }
00356 
00357   *p_ncount = ncount;
00358   *p_ecount = ecount;
00359   *p_elist = elist;
00360   *p_wlist = wlist;
00361 
00362 CLEANUP:
00363 
00364   if (f)
00365     fclose (f);
00366   return rval;
00367 }
00368 
00369 
00370 int buildgraph (int ecount,
00371                 int *elist,
00372                 double *wlist,
00373                 DPspanningEdge ** p_edglist)
00374 {
00375   DPspanningEdge *edglist = (DPspanningEdge *) NULL;
00376   int i,
00377     rval = 0;
00378 
00379   edglist = (DPspanningEdge *) malloc (ecount * sizeof (DPspanningEdge));
00380   if (!edglist)
00381   {
00382     fprintf (stderr, "out of memory for edglist\n");
00383     rval = 1;
00384     goto CLEANUP;
00385   }
00386 
00387   for (i = 0; i < ecount; i++)
00388   {
00389     edglist[i].ends[0] = elist[2 * i];
00390     edglist[i].ends[1] = elist[2 * i + 1];
00391     edglist[i].weight = wlist[i];
00392   }
00393 
00394   *p_edglist = edglist;
00395 
00396 CLEANUP:
00397 
00398   return rval;
00399 }
00400 
00401 /* disjoint sets ala Tarjan (from Data Structures and Network Algorithms
00402    by Robert Tarjan) */
00403 
00404 void makeset (DPspanningNode * v)
00405 {
00406   v->setinfo.parent = v;
00407   v->setinfo.rank = 0;
00408 }
00409 
00410 DPspanningNode *find (DPspanningNode * v)
00411 {
00412   DPspanningNode *p = v->setinfo.parent;
00413 
00414   return v == p ? v : (v->setinfo.parent = find (p));
00415 }
00416 
00417 DPspanningNode *slink (DPspanningNode * x,
00418                        DPspanningNode * y)
00419 {
00420   DPspanningNode *t;
00421   if (x->setinfo.rank > y->setinfo.rank)
00422   {
00423     SWAP (x, y, t);
00424   }
00425   else if (x->setinfo.rank == y->setinfo.rank)
00426   {
00427     y->setinfo.rank++;
00428   }
00429   x->setinfo.parent = y;
00430   return y;
00431 }

Generated on Thu Oct 20 14:58:40 2005 for DominoParitySeparator by  doxygen 1.4.5