#include <stdio.h>
#include <stdlib.h>
enum nodes {A=0, B, C, D, E, F, G, H, I, end}; // first and last elements are implicitly the start and end nodes
// A B C D E F G H I, end
int duration [] = { 13, 6, 6, 6, 10 , 20, 8, 12, 5, 0};
int link[] = {1<<B | 1<<E | 1<<G, 1<<C, 1<<D, 1<<I, 1<<F, 1<<I, 1<<H, 1<<I, 1<<end, 0};
int backlink[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int ES[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int EF[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int LS[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int LF[] = { 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999,9999, 9999}; // infinite
void WalkForward(int this_node) {
int next_node;
for (next_node = 1; next_node < 27; next_node++) {
if (link[this_node] & (1<<next_node)) { // there exists a path from this_node to next_node;
backlink[next_node] |= 1<<this_node; // remember the path back
EF[this_node] = ES[this_node] + duration[this_node];
if (EF[this_node] > ES[next_node]) ES[next_node] = EF[this_node]; // take the high road
WalkForward(next_node);
}
}
}
void WalkBackward(int this_node) {
int prev_node;
if (this_node < 0) return;
LS[this_node] = LF[this_node] - duration[this_node];
for (prev_node = 26; prev_node >= 0; prev_node--) { // we already noted the back links
if (backlink[this_node] & (1<<prev_node)) {
if (LS[this_node] < LF[prev_node]) LF[prev_node] = LS[this_node]; // take the low road
WalkBackward(prev_node);
}
}
}
void CriticalPath(int this_node) {
int prev_node;
if (this_node < 0) return;
for (prev_node = 26; prev_node >= 0; prev_node--) {
if ((backlink[this_node] & (1<<prev_node)) && (LS[prev_node]-ES[prev_node] <= 0)) {
CriticalPath(prev_node); putchar(prev_node+'A');
}
}
}
void AllPaths(int this_node, int path, int total_duration)
{
int node, next_node, ef, branches = 0;
for (next_node = 1; next_node < 27; next_node++) {
if (link[this_node] & (1<<next_node)) { // there exists a path from this_node to next_node;
branches++; AllPaths(next_node, path | (1<<this_node), total_duration+duration[this_node]);
}
}
if (branches == 0) {
for (node = 0; node < 27; node++) if (path & (1<<node)) putchar(node+'A');
printf(": %d\n", total_duration);
}
}
int main(int argc, char **argv) {
int node = 0;
WalkForward(A);
LF[I] = EF[I]; // Anti-symmetric
WalkBackward(I);
do {
printf(" %c(%2d): [ES: %2d EF: %2d / LS: %2d LF: %2d] total float = %2d\n",
node+'A', duration[node], ES[node], EF[node], LS[node], LF[node], LS[node]-ES[node]);
} while (link[++node] != 0);
printf("\nAll paths:\n"); AllPaths(A, 0, 0);
printf("\nCritical path: "); CriticalPath(node); putchar('\n');
exit(0); return(1);
}