/************************************************************************/ /* prim.cpp */ /* */ /* Written by: Virgil Bistriceanu */ /* Date: March 21, 1997 */ /* Environment: UNIX, Borland C++ 4.52 */ /* Usage: prim */ /* */ /* Implements Prim's algorithm for finding the minimum spanning tree of */ /* a connected weighted graph. Reads input from stdin, prints output to */ /* stdout. */ /* The first line in the input conteins the number of vertices. */ /* The second line contains the starting vertex for the algorithm. This */ /* is a deviation from the original Prim's algorithm, but the results */ /* should not change. */ /* Every subsequent line has the following format: */ /* vertex_i vertex_j weight */ /* where `weight' is an integer */ /* */ /************************************************************************/ #include #include #include #include /* Maximum number of nodes in the graph */ #define MAX_VERTICES 64 #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif /* Use BLACK to mark a vertex that has been visited and WHITE for one that hasn't been yet. */ #define NOT_INTREE 2 #define INTREE 3 /* Maximum length of a line in the input */ #define MAXLINE 256 #define errline(S) fprintf(stderr, "*** Line %d: %s\n", linenum, S); /***************************/ /* Data structures */ /***************************/ typedef struct edge { int v1; /* one end of the edge */ int v2; /* the other end of the edge */ int weight; /* weight of this edge */ } EDGE; typedef struct tree_stack { int tos; /* top of stack is the first free position */ EDGE s[MAX_VERTICES]; /* the stack itself as an array */ } TSTACK; int Graph[MAX_VERTICES][MAX_VERTICES]; /* graph matrix with weights */ int InTree[MAX_VERTICES]; /* mark with INTREE a vertex in the tree */ int Vertices; /* the number of nodes in the graph */ int Start; /* starting vertex */ /* Edges in the tree constructed so far are kept in a stack called Current_tree. */ TSTACK Current_tree; /* Candidate edges for the next edge to be added in the spanning tree are kept in a stack called Candidate_edges. Then the minimum edge is found and pushed in `Current_tree', i.e. is added to the minimum spanning tree. */ TSTACK Candidate_edges; /***************************/ /* Stack Functions */ /***************************/ static void init_stack(TSTACK *stack) { stack->tos = 0; } static void push_stack(TSTACK *stack, EDGE edge) { stack->s[stack->tos] = edge; stack->tos++; } static EDGE pop_stack(TSTACK *stack) { stack->tos--; return stack->s[stack->tos]; } int empty_stack(TSTACK *stack) { if (stack->tos == 0) return TRUE; return FALSE; } /*********************/ /* Functions */ /*********************/ /* edge_exists() returns TRUE if this edge exists in the graph. Used to check against multiple instances of the same edge in the input. */ static int edge_exists(int v1, int v2) { if (Graph[v1][v2] != 0) return TRUE; return FALSE; } /* read_input() reads from standard input. Stores the number of vertices in the graph (first line in the input) in global `Vertices', the starting vertex (the second line in the input) in global `Start', and the graph description in `Graph' */ static void read_input() { int linenum = 1; /* line number in the input */ int v1, v2, weight; /* edge description from input */ char line[MAXLINE]; /* used in the macro readline */ if (fgets(line, MAXLINE, stdin) != NULL) { sscanf(line, "%d", &Vertices); /* first line is number of vertices */ } else { errline("Unexpected EOF"); exit(1); } linenum++; if (fgets(line, MAXLINE, stdin) != NULL) { sscanf(line, "%d", &Start); /* second line is starting vertex */ } else { errline("Unexpected EOF"); exit(1); } linenum++; while (fgets(line, MAXLINE, stdin)) { linenum++; /* line we are at in input */ v1=v2=weight=INT_MAX; sscanf(line, "%d%d%d", &v1, &v2, &weight); if (v1 == INT_MAX || v2 == INT_MAX || weight == INT_MAX) { fprintf(stderr, "*** Line %d: incomplete line.\n", linenum); exit(4); } if (edge_exists(v1, v2)) { fprintf(stderr, "*** Line %d: edge (%d, %d) redeclared\n", \ linenum, v1, v2); exit(3); } Graph[v1][v2] = weight; Graph[v2][v1] = weight; /* make sure the matrix is symmetric */ } } static void output_result() { int total=0; EDGE edge; printf("vertex_i\tvertex_j\tDistance\n"); printf("----------------------------------------------\n"); while (!empty_stack(&Current_tree)) { edge = pop_stack(&Current_tree); printf("%8d\t%8d\t%8d\n", edge.v1, edge.v2, edge.weight); total = total+edge.weight; } printf("----------------------------------------------\n"); printf("Total distance:\t\t\t%8d\n", total); } /* find_candidates() finds all edges whose one end is in the spanning tree already built (`Current_tree'), and the other end is not. Each such edge is pushed in `Candidate_edges()' */ static void find_candidates() { int i, j; EDGE edge; init_stack(&Candidate_edges); for (i=0; i