Guest User

Untitled

a guest
Oct 21st, 2017
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.06 KB | None | 0 0
  1. //struct for subsets used in MST Kruskal algoritm
  2. typedef struct subset {
  3. int parent;
  4. int rank;
  5. } subset_t, *subset_p;
  6.  
  7. //struct for storing graph edges
  8. typedef struct edges {
  9. int src;
  10. int dest;
  11. int weight;
  12. } edges_t, *edges_p;
  13.  
  14. //struct for storing weights and number of their occuriences
  15. typedef struct weights {
  16. int weight;
  17. int occurCount;
  18. } weights_t, *weights_p;
  19.  
  20. //struct to store all built trees
  21. typedef struct trees {
  22.  
  23. int totalWeight; // total tree weight
  24. int mostOccurNumber; // highest number of repeated edges for a tree
  25. } trees_t, *trees_p;
  26.  
  27. //find and union function prototypes
  28. int find(struct subset subsets[], int i);
  29. void Union(struct subset subsets[], int x, int y);
  30.  
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include "header.h"
  34.  
  35. //find function used in Kruskals algorithm
  36. int find(subset_p subsets, int i) {
  37. if (subsets[i].parent != i) {
  38. subsets[i].parent = find(subsets, subsets[i].parent);
  39. }
  40. return subsets[i].parent;
  41. }
  42.  
  43. //union function used in Kruskals algorithm
  44. void Union(subset_p subsets, int x, int y) {
  45. int xroot = find(subsets, x);
  46. int yroot = find(subsets, y);
  47.  
  48. if (subsets[xroot].rank < subsets[yroot].rank) {
  49. subsets[xroot].parent = yroot;
  50. } else if (subsets[xroot].rank > subsets[yroot].rank) {
  51. subsets[yroot].parent = xroot;
  52. } else {
  53. subsets[yroot].parent = xroot;
  54. subsets[xroot].rank++;
  55. }
  56. }
  57. //compare function used in qsort(). Sorts all edges by ascending weight
  58. int myComp1 (const void *a, const void *b)
  59. {
  60. const edges_t * ptr_a = (const edges_t *)a;
  61. const edges_t * ptr_b = (const edges_t *)b;
  62. if (ptr_a->weight < ptr_b->weight) return -1;
  63. if (ptr_a->weight > ptr_b->weight) return 1;
  64. return 0;
  65. }
  66. //Sorts all present weights by descending number of occuriences in the MST
  67. int myComp2 (const void *a, const void *b)
  68. {
  69. const weights_t * ptr_a = (const weights_t *)a;
  70. const weights_t * ptr_b = (const weights_t *)b;
  71. if (ptr_a->occurCount > ptr_b->occurCount) return -1;
  72. if (ptr_a->occurCount < ptr_b->occurCount) return 1;
  73. return 0;
  74. }
  75. //Sorts all present MSTs primarily by descending number of same-weight occuriences
  76. //Secondly by ascending weights
  77. int myComp3 (const void *a, const void *b)
  78. {
  79. const weights_t * ptr_a = (const weights_t *)a;
  80. const weights_t * ptr_b = (const weights_t *)b;
  81. int diff = ptr_b->occurCount - ptr_a->occurCount;
  82. if (diff == 0) {
  83. if (ptr_a->weight < ptr_b->weight) {
  84. diff = -1;
  85. } else if (ptr_a->weight > ptr_b->weight) {
  86. diff = 1;
  87. } else diff = 0;
  88. }
  89. return diff;
  90. }
  91.  
  92. int main() {
  93. //number of vertices and edges for a graph
  94. int num_vertices, num_edges;
  95. scanf("%d%d", &num_vertices, &num_edges);
  96.  
  97. // struct to keep all graph edges
  98. edges_p allEdges = (edges_p)malloc(num_edges*sizeof(edges_t));
  99.  
  100. //input variables for source vertex, destanation vertex and weight of the edge
  101. int curr_src, curr_dest, curr_weight;
  102.  
  103. //array to store all present (different!) weight values
  104. int * weights = (int *)malloc(num_edges*sizeof(int));
  105.  
  106. //a variable to store number of elements in 'weights' array - number of different weight values in a graph
  107. int newWeightIndex = 0;
  108.  
  109. //inputing data about graph edges: source vertex, destination vertex, weight
  110. for (int i = 0; i < num_edges; i++) {
  111. scanf("%d%d%d", &curr_src, &curr_dest, &curr_weight);
  112.  
  113. //filling array of structs with input info
  114. allEdges[i].src = curr_src - 1;
  115. allEdges[i].dest = curr_dest - 1;
  116. allEdges[i].weight = curr_weight;
  117.  
  118. //'Weights' array contains all weights that are present in a graph.
  119. //Here we decide whether we should put current weight value into an array.
  120. bool alreadyHasWeight = 0;
  121. for (int j = 0; j < i; j++) {
  122. if (weights[j] == curr_weight) {
  123. alreadyHasWeight = 1;
  124. break;
  125. }
  126. }
  127. if (alreadyHasWeight == 0) {
  128. weights[newWeightIndex] = curr_weight;
  129. newWeightIndex++;
  130. }
  131. }
  132. // end of data input
  133.  
  134. //an array of structs to store info about build MSTs (the weight of MST and maximum number of edges with same weights)
  135. trees_p myTrees = (trees_p)malloc(newWeightIndex * sizeof(trees_t));
  136.  
  137. //Kruscal Algoritm lopp to find an MST for all present weights.
  138. //We take each weight in 'weights' and change the weight of every edge in a graph that has weight equal to 'weights[i]' to -1
  139. for (int i = 0; i < newWeightIndex; i++) {
  140. int minimizedWeight = weights[i];
  141.  
  142. //array to store subsets of vertices
  143. subset_p subsets = (subset_p)malloc(num_vertices * sizeof(subset_t));
  144.  
  145. //array to store MST Edges
  146. edges_p mstEdges = (edges_p)malloc(num_vertices*sizeof(edges_t));
  147.  
  148. //array to store current edge
  149. edges_p currentEdge = (edges_p)malloc(sizeof(edges_t));
  150.  
  151. //variable to keep the amount of weight that was subtracted (when setting some weights to -1)
  152. //this is done in order to restore default weights after MST build finishes
  153. int subtractedWeight = 0;
  154.  
  155. //variable to keep the number of edges which weight was changed to -1
  156. int infEdgesTotal = 0;
  157.  
  158. //variable to keep the number of edges which weight was changed to -1 included to MST
  159. int infEdgesTaken = 0;
  160.  
  161. //setting minimum weights
  162. for (int i = 0; i < num_edges; i++) {
  163. if (allEdges[i].weight == minimizedWeight) {
  164. allEdges[i].weight = -1;
  165. subtractedWeight += minimizedWeight+1;
  166. infEdgesTotal++;
  167. }
  168. }
  169.  
  170. //sorting all graph edges in ascending order
  171. qsort(allEdges, num_edges, sizeof(edges_t), myComp1);
  172.  
  173. //the kruskal algoritm itself - BEGINNING
  174. for (int v = 0; v < num_vertices; v++) {
  175. subsets[v].parent = v;
  176. subsets[v].rank = 0;
  177. }
  178.  
  179. int e = 0;
  180. int currentIndex = 0;
  181. int mstWeight = 0;
  182. int mstEdgesCount = 0;
  183. while (e < num_vertices - 1) {
  184.  
  185. currentEdge[0].src = allEdges[currentIndex].src;
  186. currentEdge[0].dest = allEdges[currentIndex].dest;
  187. currentEdge[0].weight = allEdges[currentIndex].weight;
  188.  
  189. int x = find(subsets, currentEdge[0].src);
  190. int y = find(subsets, currentEdge[0].dest);
  191. currentIndex++;
  192.  
  193. if (x != y) {
  194. mstEdges[e].src = currentEdge[0].src;
  195. mstEdges[e].dest = currentEdge[0].dest;
  196. mstEdges[e].weight = currentEdge[0].weight;
  197. mstWeight += mstEdges[e].weight;
  198. mstEdgesCount++;
  199. if (mstEdges[e].weight == -1) {
  200. infEdgesTaken++;
  201. }
  202. e++;
  203. Union(subsets, x, y);
  204. }
  205.  
  206. }
  207. free(subsets);
  208. //the kruskal algoritm itself - END
  209.  
  210. //Restoring default weights
  211. for (int i = 0; i < num_edges; i++) {
  212. if (allEdges[i].weight == -1) {
  213. allEdges[i].weight += minimizedWeight+1;
  214. }
  215. }
  216.  
  217. //Calculating built MST weight
  218. mstWeight += subtractedWeight/infEdgesTotal*infEdgesTaken;
  219.  
  220. //an array to store all weight values in MST and a number of edges in MST with that weight
  221. weights_p myWeights = (weights_p)malloc(mstEdgesCount*sizeof(weights_t));
  222.  
  223. //a variable to store the number of different weight values in MST
  224. int num_weights = 0;
  225.  
  226. //filling 'myWeights' array
  227. for(int i = 0; i < mstEdgesCount; i++) {
  228. myWeights[i].weight = -100;
  229. }
  230. for (int i = 0; i < mstEdgesCount; i++) {
  231. for (int j = 0; j < i + 1; j++) {
  232. if (myWeights[j].weight == -100) {
  233. myWeights[j].weight = mstEdges[i].weight;
  234. myWeights[j].occurCount = 1;
  235. num_weights++;
  236. break;
  237. } else if (myWeights[j].weight != mstEdges[i].weight){
  238. continue;
  239. } else {
  240. myWeights[j].occurCount++;
  241. break;
  242. }
  243. }
  244. }
  245.  
  246. free(currentEdge);
  247.  
  248. //sorting all present weights by descending number of edges with that weight
  249. qsort(myWeights, num_weights, sizeof(weights_t), myComp2);
  250.  
  251. //a variable to store a maximum number of weight occuriences in MST
  252. int mostOccs = myWeights[0].occurCount;
  253.  
  254. free(myWeights);
  255. free(mstEdges);
  256.  
  257. //adding info about current MST into 'myTrees' array
  258. myTrees[i].totalWeight = mstWeight;
  259. myTrees[i].mostOccurNumber = mostOccs;
  260. }
  261. // End of Krushkal Algorithm iteration
  262.  
  263. free(weights);
  264. free(allEdges);
  265.  
  266. //sorting 'myTrees' array to get an MST with maximum number of same-edge occuriences
  267. //and lowest weight in the top
  268. qsort(myTrees, newWeightIndex, sizeof(trees_t), myComp3);
  269.  
  270. //outputing the result
  271. printf ("%d",myTrees[0].totalWeight);
  272.  
  273. free(myTrees);
  274. system("pause");
  275. return 0;
  276. }
Add Comment
Please, Sign In to add comment