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
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
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
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
00402
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 }