static int setall = 0; /* if false, don't set dist attribute for
* nodes in different components.
*/
+static int doPath = 0; /* if 1, record shortest paths */
static Agsym_t *len_sym;
typedef struct nodedata_s {
Agrec_t hdr;
double dist; /* always positive for scanned nodes */
+ Agnode_t* prev;
} nodedata_t;
typedef struct edgedata_s {
#else
#define getdist(n) (((nodedata_t*)((n)->base.data))->dist)
#define setdist(n,d) (((nodedata_t*)((n)->base.data))->dist = (d))
+#define getprev(n) (((nodedata_t*)((n)->base.data))->prev)
+#define setprev(n,p) (((nodedata_t*)((n)->base.data))->prev = (p))
#endif
static int cmpf(Dt_t * d, void *key1, void *key2, Dtdisc_t * disc)
if (oldlen == 0) { /* first time to see dest */
setdist(dest, newlen);
+ if (doPath) setprev(dest, src);
dtinsert(Q, dest);
} else if (newlen < oldlen) {
dtdelete(Q, dest);
setdist(dest, newlen);
+ if (doPath) setprev(dest, src);
dtinsert(Q, dest);
}
}
static void post(Agraph_t * g)
{
Agnode_t *v;
+ Agnode_t *prev;
char buf[256];
char dflt[256];
Agsym_t *sym;
+ Agsym_t *psym;
double dist, oldmax;
double maxdist = 0.0; /* maximum "finite" distance */
sym = agattr(g, AGNODE, "dist", "");
+ if (doPath)
+ psym = agattr(g, AGNODE, "prev", "");
if (setall)
sprintf(dflt, "%.3lf", HUGE);
dist--;
sprintf(buf, "%.3lf", dist);
agxset(v, sym, buf);
+ if (doPath && (prev = getprev(v)))
+ agxset(v, psym, agnameof(prev));
if (maxdist < dist)
maxdist = dist;
} else if (setall)
static char *useString =
"Usage: dijkstra [-a?] <node> [<file> <node> <file>]\n\
-a - for nodes in a different component, set dist very large\n\
+ -p - attach shortest path info\n\
-? - print usage\n\
If no files are specified, stdin is used\n";
int i, j, c;
CmdName = argv[0];
- while ((c = getopt(argc, argv, ":a?")) != -1) {
+ while ((c = getopt(argc, argv, ":ap?")) != -1) {
switch (c) {
case 'a':
setall = 1;
break;
+ case 'p':
+ doPath = 1;
+ break;
case '?':
if (optopt == '?')
usage(0);