/* Critical_path is much more useful in our life. * just be opposite to the so called "Bucket Principle", * the total time of one project is detemined by the cumulative * longest time of its components. When there are many components * in one project between which are many decisive relationships, * it is hard for one to calculate the accurate time needed for the * porject immediately. The following code is writen for this purpose. * Version: 0.1; by: double; date:2009-07-05 */ #include "/usr/c/head.h" #define MAX 20 #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 #define SCAN_INT(x, y); if (scanf("%d", &x) != EOF) while ((y = getchar()) != '/n' && y != EOF) {;} /* This time I replace the cumbersome "if () while () {;}" sentence with a MACRO.Now, it looks much better. * Take care, the formal parameter "x" can not be a pointer. This is quite important. The formal parameter "y" must be a integer. * In the code, I define a integer of temp, it is used specially for this purpose. */ #define SCAN_CHAR(x, y); if (scanf("%c", &x) != EOF) while ((y = getchar()) != '/n' && y != EOF) {;} typedef char vertex_type; typedef int info_type; typedef struct arc_type { int adjvex; struct arc_type * nextarc; info_type * info; }arc_type; typedef struct vex_type { vertex_type data; arc_type * firstarc; }vex_type; typedef struct al_graph { vex_type vexs[MAX]; int vexnum, arcnum; }al_graph; typedef int stack_element_type; /* sequence stack is defined*/ typedef struct sq_stack { stack_element_type * base; stack_element_type * top; int stack_size; }sq_stack; /* The global variable*/ al_graph G; sq_stack S, T; int degree[MAX]; int count = 0; int ve[MAX]; int vl[MAX]; status init_stack(sq_stack * S) { S->base = S->top = (stack_element_type *)malloc(sizeof(stack_element_type) * STACK_INIT_SIZE); if (!S->base) exit(OVERFLOW); S->stack_size = STACK_INIT_SIZE; return OK; } status push(sq_stack * S, stack_element_type e) { if (S->top - S->base >= S->stack_size) { S->base = (stack_element_type *)realloc(S->base, (S->stack_size + STACKINCREMENT) * sizeof(stack_element_type)); if (!S->base) exit(OVERFLOW); S->top = S->base + S->stack_size; S->stack_size += STACKINCREMENT; printf("Realloc OK!/n"); } *S->top = e; S->top++; return OK; } status pop(sq_stack * S, stack_element_type * e) { if (S->base == S->top) { printf("Stack empty!/n"); exit(ERROR); } S->top--; *e = *S->top; return OK; } int stack_empty(sq_stack S) { if (S.top == S.base) return 1; return 0; } int locate_vex(al_graph G, vertex_type v) { int i; for (i = 0; i < G.vexnum; i++) if (G.vexs[i].data == v) return i; return -1; } status init_graph(al_graph * G) { int temp, i, p1, p2; vertex_type v1, v2; arc_type * p; printf("Input the vexnum:"); SCAN_INT(G->vexnum, temp); for (i = 0; i < G->vexnum; i++) { printf("No.%d:", i + 1); SCAN_CHAR(G->vexs[i].data, temp); G->vexs[i].firstarc = NULL; } printf("Input the arcnum:"); SCAN_INT(G->arcnum, temp); for (i = 0; i < G->arcnum; i++) { printf("No.%d, v1:", i + 1); SCAN_CHAR(v1, temp); printf("No.%d, v2:", i + 1); SCAN_CHAR(v2, temp); p1 = locate_vex(*G, v1); if (p1 == -1) { printf("v1 = %c out of range!/n", v1); exit(ERROR); } p2 = locate_vex(*G, v2); if (p2 == -1) { printf("v2 = %c out of range!/n", v2); exit(ERROR); } p = (arc_type *)malloc(sizeof(arc_type)); if (!p) exit(OVERFLOW); p->adjvex = p2; p->info = (info_type *)malloc(sizeof(info_type)); printf("Weight:"); SCAN_INT(*p->info, temp); p->nextarc = G->vexs[p1].firstarc; G->vexs[p1].firstarc = p; } return OK; } status print_graph(al_graph G) { int i; arc_type * p; printf("Vertex are:/n"); for (i = 0; i < G.vexnum; i++) printf("%c/t", G.vexs[i].data); printf("/n"); printf("Arch are:/n"); for (i = 0; i < G.vexnum; i++) { for (p = G.vexs[i].firstarc; p; p = p->nextarc) printf("(%c, %c) %d/t", G.vexs[i].data, G.vexs[p->adjvex].data, p->info); printf("/n"); } return OK; } status find_in_degree(al_graph G, int * degree) { int i; arc_type * p; for (i = 0; i < G.vexnum; i++) for (p = G.vexs[i].firstarc; p; p = p->nextarc) degree[p->adjvex]++; return OK; } status topological_sort(al_graph G, int * degree) { int i, j; arc_type * p; init_stack(&S); init_stack(&T); for (i = 0; i < G.vexnum; i++) ve[i] = 0; find_in_degree(G, degree); for (i = 0; i < G.vexnum; i++) if (degree[i] == 0) push(&S, i); while(!stack_empty(S)) { pop(&S, &j); push(&T, j); count++; printf("%c/t", G.vexs[j].data); for (p = G.vexs[j].firstarc; p; p = p->nextarc) { degree[p->adjvex]--; if (degree[p->adjvex] == 0) push(&S, p->adjvex); if (ve[p->adjvex] < ve[j] + *p->info) ve[p->adjvex] = ve[j] + *p->info; } } printf("/n"); if (count < G.vexnum) { printf("Graph is not topological sorted!/n"); return ERROR; } return OK; } status critical_path(al_graph G) { int i, j; arc_type *p; if (topological_sort(G, degree) == ERROR) exit(ERROR); for (i = 0; i < G.vexnum; i++) vl[i] = ve[G.vexnum - 1]; while (!stack_empty(T)) { pop(&T, &j); for (p = G.vexs[j].firstarc; p; p = p->nextarc) if (vl[j] > vl[p->adjvex] - *p->info) vl[j] = vl[p->adjvex] - *p->info; } for (i = 0; i < G.vexnum; i++) for (p = G.vexs[i].firstarc; p; p = p->nextarc) if (ve[i] == vl[p->adjvex] - *p->info) printf("%c->%c/t", G.vexs[i].data, G.vexs[p->adjvex].data); printf("/n"); return OK; } int main(void) { init_graph (&G); printf("Graph initilized OK!/nThe critical path is:/n"); /*print_graph(G);*/ critical_path(G); return 0; }