-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparallel_mst.c
More file actions
128 lines (106 loc) · 3.67 KB
/
Copy pathparallel_mst.c
File metadata and controls
128 lines (106 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#define INF 1000000 // A large value representing infinity
// Edge structure
typedef struct {
int src, dest, weight;
} Edge;
// Function to find the parent of a vertex (union-find)
int find(int parent[], int vertex) {
if (parent[vertex] != vertex)
parent[vertex] = find(parent, parent[vertex]); // Path compression
return parent[vertex];
}
// Function to unite two sets
void unite(int parent[], int rank[], int x, int y) {
int rootX = find(parent, x);
int rootY = find(parent, y);
if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else if (rank[rootX] > rank[rootY]) {
parent[rootY] = rootX;
} else {
parent[rootY] = rootX;
rank[rootX]++;
}
}
// Borůvka's algorithm for MST
void boruvkaMST(Edge edges[], int V, int E, int num_threads) {
int *parent = (int *)malloc(V * sizeof(int));
int *rank = (int *)malloc(V * sizeof(int));
int *cheapest = (int *)malloc(V * sizeof(int));
int num_components = V;
int MST_weight = 0;
// Initialize union-find sets
for (int i = 0; i < V; i++) {
parent[i] = i;
rank[i] = 0;
cheapest[i] = -1;
}
omp_set_num_threads(num_threads);
while (num_components > 1) {
// Reset cheapest array
for (int i = 0; i < V; i++) {
cheapest[i] = -1;
}
// Find cheapest edge for each component in parallel
#pragma omp parallel for
for (int i = 0; i < E; i++) {
int u = find(parent, edges[i].src);
int v = find(parent, edges[i].dest);
if (u != v) { // Only consider edges between different components
#pragma omp critical
{
if (cheapest[u] == -1 || edges[i].weight < edges[cheapest[u]].weight) {
cheapest[u] = i;
}
if (cheapest[v] == -1 || edges[i].weight < edges[cheapest[v]].weight) {
cheapest[v] = i;
}
}
}
}
// Add selected edges to MST
for (int i = 0; i < V; i++) {
if (cheapest[i] != -1) {
int u = find(parent, edges[cheapest[i]].src);
int v = find(parent, edges[cheapest[i]].dest);
if (u != v) {
MST_weight += edges[cheapest[i]].weight;
printf("Adding edge: %d -- %d (Weight: %d)\n",
edges[cheapest[i]].src, edges[cheapest[i]].dest,
edges[cheapest[i]].weight);
unite(parent, rank, u, v);
num_components--;
}
}
}
}
printf("Total weight of MST: %d\n", MST_weight);
free(parent);
free(rank);
free(cheapest);
}
int main() {
int V, E, num_threads;
printf("Enter the number of vertices: ");
scanf("%d", &V);
printf("Enter the number of edges: ");
scanf("%d", &E);
Edge *edges = (Edge *)malloc(E * sizeof(Edge));
printf("Enter the edges (src dest weight):\n");
for (int i = 0; i < E; i++) {
scanf("%d %d %d", &edges[i].src, &edges[i].dest, &edges[i].weight);
}
printf("Enter the number of threads to use: ");
scanf("%d", &num_threads);
// Measure execution time
double start_time = omp_get_wtime();
printf("Finding MST using Borůvka's Algorithm with %d threads...\n", num_threads);
boruvkaMST(edges, V, E, num_threads);
double end_time = omp_get_wtime();
printf("Execution time with %d threads: %f seconds\n", num_threads, end_time - start_time);
free(edges);
return 0;
}