@@ -123,5 +123,104 @@ const MstResult Graph<T>::boruvka() const {
123
123
return result;
124
124
}
125
125
126
+ template <typename T>
127
+ const MstResult Graph<T>::boruvka_deterministic() const {
128
+ MstResult result;
129
+ result.success = false ;
130
+ result.errorMessage = " " ;
131
+ result.mstCost = INF_DOUBLE;
132
+ if (!isUndirectedGraph ()) {
133
+ result.errorMessage = ERR_DIR_GRAPH;
134
+ return result;
135
+ }
136
+ const auto nodeSet = Graph<T>::getNodeSet ();
137
+ const auto n = nodeSet.size ();
138
+
139
+ // Use std map for storing n subsets.
140
+ auto subsets = make_shared<std::unordered_map<CXXGraph::id_t , Subset>>();
141
+
142
+ // Initially there are n different trees.
143
+ // Finally there will be one tree that will be MST
144
+ auto numTrees = n;
145
+
146
+ // check if all edges are weighted and store the weights
147
+ // in a map whose keys are the edge ids and values are the edge weights
148
+ const auto edgeSet = Graph<T>::getEdgeSet ();
149
+ std::unordered_map<CXXGraph::id_t , double > edgeWeight;
150
+ for (const auto &edge : edgeSet) {
151
+ if (edge->isWeighted ().has_value () && edge->isWeighted ().value ())
152
+ edgeWeight[edge->getId ()] =
153
+ (std::dynamic_pointer_cast<const Weighted>(edge))->getWeight ();
154
+ else {
155
+ // No Weighted Edge
156
+ result.errorMessage = ERR_NO_WEIGHTED_EDGE;
157
+ return result;
158
+ }
159
+ }
160
+
161
+ for (const auto &node : nodeSet) {
162
+ Subset set{node->getId (), 0 };
163
+ (*subsets)[node->getId ()] = set;
164
+ }
165
+
166
+ result.mstCost = 0 ; // we will store the cost here
167
+ // exit when only 1 tree i.e. mst
168
+ while (numTrees > 1 ) {
169
+ // Everytime initialize cheapest map
170
+ // It stores index of the cheapest edge of subset.
171
+ std::unordered_map<CXXGraph::id_t , CXXGraph::id_t > cheapest;
172
+ for (const auto &node : nodeSet) cheapest[node->getId ()] = INT_MAX;
173
+
174
+ // Traverse through all edges and update
175
+ // cheapest of every component
176
+ for (const auto &edge : edgeSet) {
177
+ auto elem = edge->getNodePair ();
178
+ auto edgeId = edge->getId ();
179
+ // Find sets of two corners of current edge
180
+ auto set1 = Graph<T>::setFind (subsets, elem.first ->getId ());
181
+ auto set2 = Graph<T>::setFind (subsets, elem.second ->getId ());
182
+
183
+ // If two corners of current edge belong to
184
+ // same set, ignore current edge
185
+ if (set1 == set2) continue ;
186
+
187
+ // Else check if current edge is closer to previous
188
+ // cheapest edges of set1 and set2
189
+ if (cheapest[set1] == INT_MAX ||
190
+ (edgeWeight[cheapest[set1]] > edgeWeight[edgeId]) ||
191
+ (edgeWeight[cheapest[set1]] == edgeWeight[edgeId] && cheapest[set1] > edgeId)
192
+ )
193
+ cheapest[set1] = edgeId;
194
+
195
+ if (cheapest[set2] == INT_MAX ||
196
+ (edgeWeight[cheapest[set2]] > edgeWeight[edgeId]) ||
197
+ (edgeWeight[cheapest[set2]] == edgeWeight[edgeId] && cheapest[set2] > edgeId)
198
+ )
199
+ cheapest[set2] = edgeId;
200
+ }
201
+
202
+ // iterate over all the vertices and add picked
203
+ // cheapest edges to MST
204
+ for (const auto &[nodeId, edgeId] : cheapest) {
205
+ // Check if cheapest for current set exists
206
+ if (edgeId != INT_MAX) {
207
+ auto cheapestNode = Graph<T>::getEdge (edgeId).value ()->getNodePair ();
208
+ auto set1 = Graph<T>::setFind (subsets, cheapestNode.first ->getId ());
209
+ auto set2 = Graph<T>::setFind (subsets, cheapestNode.second ->getId ());
210
+ if (set1 == set2) continue ;
211
+ result.mstCost += edgeWeight[edgeId];
212
+ auto newEdgeMST = std::make_pair (cheapestNode.first ->getUserId (),
213
+ cheapestNode.second ->getUserId ());
214
+ result.mst .push_back (newEdgeMST);
215
+ // take union of set1 and set2 and decrease number of trees
216
+ Graph<T>::setUnion (subsets, set1, set2);
217
+ numTrees--;
218
+ }
219
+ }
220
+ }
221
+ result.success = true ;
222
+ return result;
223
+ }
224
+
126
225
} // namespace CXXGraph
127
226
#endif // __CXXGRAPH_BORUVKA_IMPL_H__
0 commit comments