//Author: Kevin Achenbach
//Date: 4/20/14
//Description: Given coordinates, will find the total distance of a MST
// using Prim and Kruskals MST
#include <stdio.h>
#include <math.h>
//distance can not be greater than INF
#define INF 100000
//probably unneccessary, just make array if time
struct Vertex {
int rep;
};
void prim(int numinput, double graph[][2]);
void kruskal(int numinput, double graph[][2]);
void unionVert(struct Vertex[],int len, int rep1, int rep2);
/* Expected input:
# of test cases
# of coordinates
x1coord y2coord
etc..
*/
int main() {
int testcase, numinput, i, j;
scanf("%d", &testcase);
for(j=0; j<testcase; j++){
scanf("%d", &numinput);
double graph[numinput][2];
//get input and place in graph array
for(i=0;i<numinput; i++) {
scanf("%lf", &graph[i][0]);
scanf("%lf", &graph[i][1]);
}
prim(numinput, graph);
kruskal(numinput, graph);
}
return 0;
}
struct Edge {
double weight;
int p1, p2;
};
// Kruskal union, makes 2 trees into 1
void unionVert(struct Vertex* vertGraph,int len, int rep1, int rep2) {
int i;
if(rep1<rep2)
for(i=0; i<len; i++) {
if(vertGraph[i].rep == rep2) {
vertGraph[i].rep = rep1;
}
}
else {
for(i=0; i<len; i++) {
if(vertGraph[i].rep == rep1) {
vertGraph[i].rep = rep2;
}
}
}
}
void kruskal(int numinput, double graph[][2]) {
//pg 631 MST-Kruskal ALG
//First checks for <2 inputs
if(!numinput) {
printf("\nError: Number of inputs must be greater than 0\n");
return;
}
else if(numinput == 1) {
printf("\n0.00\n");
return;
}
//total number of unique distances is given by n(n-1)/2
int totalNumDist = (numinput*(numinput-1))/2;
//contains all edges
struct Edge edgeGraph[totalNumDist];
int count = 0;
int i,j;
double first,second,totalDist;
//map out the distances
//only write distances once as opposed to prim's
for(i=0; i<numinput; i++) {
for(j=0; j<numinput; j++) {
if(i<j) {
first = graph[i][0]-graph[j][0];
first = pow(first,2);
second = graph[i][1]-graph[j][1];
second = pow(second,2);
first += second;
edgeGraph[count].weight= sqrt(first);
edgeGraph[count].p1 = i;
edgeGraph[count].p2 = j;
count++;
}
}
}
//insertion sort of the edges
double storeWeight;
int storeP1, storeP2;
//insertion sort to put lowest edge weights at top of the array
for(i=1; i<totalNumDist; i++) {
j=i;
while(j>0 && edgeGraph[j].weight < edgeGraph[j-1].weight) {
storeWeight = edgeGraph[j].weight;
storeP1 = edgeGraph[j].p1;
storeP2 = edgeGraph[j].p2;
edgeGraph[j].weight = edgeGraph[j-1].weight;
edgeGraph[j].p1 = edgeGraph[j-1].p1;
edgeGraph[j].p2 = edgeGraph[j-1].p2;
edgeGraph[j-1].weight = storeWeight;
edgeGraph[j-1].p1 = storeP1;
edgeGraph[j-1].p2 = storeP2;
j--;
}
}
struct Vertex vertGraph[numinput];
//each vert is a seperate tree
for(i=0; i<numinput; i++) {
vertGraph[i].rep = i;
}
//check off the first edge
totalDist = edgeGraph[0].weight;
//intial smallest edge is used to connect the seperate trees
unionVert(vertGraph, numinput, edgeGraph[0].p1, edgeGraph[0].p2);
//go through edges, smallest to largest, if they are unique trees
//union them into the same tree
for(i=1; i<totalNumDist;i++) {
if(vertGraph[edgeGraph[i].p1].rep != vertGraph[edgeGraph[i].p2].rep) {
totalDist += edgeGraph[i].weight;
unionVert(vertGraph, numinput, vertGraph[edgeGraph[i].p1].rep, vertGraph[edgeGraph[i].p2].rep);
}
}
printf("\n%.2lf\n", totalDist);
}
void prim(int numinput, double graph[][2]) {
//initial check for <2 input
if(!numinput) {
printf("\nError: Number of inputs must be greater than 0");
return;
}
else if(numinput == 1) {
printf("\n0.00\n");
return;
}
//keeps track of inputs already used
int inMST[numinput];
double distances[numinput][numinput];
int i,j,key;
double first, second;
double total = 0;
int done = 0;
//first find distance between all points
//This is a slower version than kruskal's
//it repeats distances
for(i=0; i<numinput; i++) {
//set all inMST to 0
inMST[i] = 0;
for(j=0; j<numinput; j++) {
if(i==j)
distances[i][i] == INF;
else {
first = graph[i][0]-graph[j][0];
first = pow(first,2);
second = graph[i][1]-graph[j][1];
second = pow(second,2);
first += second;
distances[i][j]= sqrt(first);
}
}
}
//Assume that vertex 0 is the starting point
inMST[0] = 1;
int count = 1;
//waits until every dist has been checked
while(!done) {
//Num of vertices in MST
double minDist = INF;
int startVert = 0;
int endVert = 0;
//find the closest vertex not yet in MST
for(i=0; i < numinput; i++) {
if(inMST[i]) {
for(j=0; j < numinput; j++) {
if(i!=j && distances[i][j] < minDist && inMST[j] == 0) {
startVert = i;
endVert = j;
minDist = distances[i][j];
}
}
}
}
//found next vertex mark it off and add edge to total
inMST[endVert] = 1;
total += minDist;
distances[startVert][endVert] = INF;
distances[endVert][startVert] = INF;
count++;
if(count >= numinput)
done++;
}
printf("\n%.2lf\n", total);
}
Sunday, July 13, 2014
Minimum Spanning Tree in C
One of my projects in algorithms class was to create a MST in C. I was given 5 sample inputs with answers, and 5 without answers. I had to create the MST using two different algorithms: Prim and Kruskal. The complete folder with the tests and results can be downloaded here. I completed this project in about 5 days.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment