-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboruvka2.cpp
125 lines (110 loc) · 3.01 KB
/
boruvka2.cpp
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
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <array>
#include <ctime>
#include <chrono>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <algorithm>
#include <set>
#include <queue>
#include "graph.h"
#include "union_find.h"
using namespace std;
int main(int argc, char ** argv){
if (argc < 3){
cout << "Usage: " << argv[0] << " n e" << endl;
cout << "n: number of nodes in graph" << endl;
cout << "e: number of edges per node" << endl;
return 1;
}
//Set cout precision
cout.precision(2);
//Set a random seed
srand(1337);
int n = atoi(argv[1]);
int edges_per_node = atoi(argv[2]);
UnionFind uf (n);
Graph g (n);
bool is_connected = false;
while (!is_connected){
for (int node_num = 0; node_num < n; node_num++){
for (int edge_num = 0; edge_num < edges_per_node; edge_num++){
//Edge from node_num to edge_num
long long weight = (rand() % 100000000) + 1;
int target = rand() % n;
g.join(node_num, target, weight);
uf.join(node_num, target);
}
}
is_connected = true;
for (int node_num = 0; node_num < n; node_num++){
if (!uf.query(node_num, 0)){
is_connected = false;
}
}
//Verifies that graph is connected
if (!is_connected){
cout << "Warning: Graph is not connected" << endl;
}
}
//cout << "Graph ready" << endl;
long long ans = 0;
chrono::high_resolution_clock::time_point start_time =
chrono::high_resolution_clock::now();
UnionFind uf_boruvka (n);
vector<long long> minWeight (n, 0);
vector<int> nearestNode (n, 0);
while (uf_boruvka.get_num_cc() > 1){
//cout << "cc: " << uf_boruvka.get_num_cc() << endl;
set<pair<int, int> > taken_edges;
//Determine minimum weight edge for each tree
for (int i = 0; i < n; i++){
minWeight[i] = 1000000000;
nearestNode[i] = -1;
}
for (int i = 0; i < n; i++){
int parent = uf_boruvka.parent(i);
for (auto it = g.adjlist[i].begin(); it != g.adjlist[i].end(); ){
int target = uf_boruvka.parent((*it).first);
long long weight = (*it).second;
if (target != parent && weight < minWeight[parent]){
minWeight[parent] = weight;
nearestNode[parent] = target;
}
if (target == parent){
it = g.adjlist[i].erase(it);
}
else{
it++;
}
}
}
for (int i = 0; i < n; i++){
//Ignore if not own parent
if (uf_boruvka.parent(i) != i){
continue;
}
//Determine new connected component
uf_boruvka.join(i, nearestNode[i]);
//Enumerate edges to prevent repeats
pair<int, int> p =
make_pair(min(i, nearestNode[i]), max(i, nearestNode[i]));
if (taken_edges.count(p) == 0){
taken_edges.insert(p);
ans += minWeight[i];
}
}
}
chrono::high_resolution_clock::time_point end_time =
chrono::high_resolution_clock::now();
cout << "n: " << n << " e: " << edges_per_node << endl;
cout << "Time Elapsed: " << scientific <<
chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count() / 1e9
<< " s" << endl;
cout << "MST Weight: " << ans << endl;
}