leetcodealgorithms-templates6-graphs
 
// Visit www.neon.rip for more!
 
#include <vector>
#include <unordered_map>
#include <utility>
#include <queue>
 
using std::vector;
using std::unordered_map;
using std::pair;
using std::tuple;
using std::get;
using std::make_tuple;
using std::make_pair;
using std::priority_queue;
using std::greater;
 
/* UnionFind implementation */
/* class UnionFind {
public:
    unordered_map<int, int> par_;
    unordered_map<int, int> rank_;
 
    UnionFind(int n) {
        for (int i = 1; i <= n; i++) {
            par_[i] = i;
            rank_[i] = 0;
        }
    }
 
    // Find parent of n, with path compression.
    int find(int n) {
        int p = par_[n];
        while (p != par_[n]) {
            par_[p] = par_[par_[p]];
            p = par_[p];
        }
        return p;
    }
 
    // Union by height / rank.
    // Return false if already connected, true otherwise.
    bool union(int n1, int n2) {
        int p1 = find(n1), p2 = find(n2);
        if (p1 == p2) {
            return false;
        }
 
        if (rank_[p1] > rank_[p2]) {
            par_[p2] = p1;
        } else if (rank_[p1] < rank_[p2]) {
            par_[p1] = p2;
        } else {
            par_[p1] = p2;
            rank_[p2] += 1;
        }
        return true;
    }
}; */
 
// Given a list of edges of a connected undirected graph,
// with nodes numbered from 1 to n,
// return a list edges making up the minimum spanning tree.
vector<pair<int, int>> mst(vector<vector<int>>& edges, int n) {
    unordered_map<int, vector<pair<int, int>>> adj;
    for (int i = 1; i < n + 1; i++) {
        adj[i] = vector<pair<int, int>>();
    }
    for (vector<int> edge : edges) {
        int n1 = edge[0], n2 = edge[1], weight = edge[2];
        adj[n1].push_back(make_pair(n2, weight));
        adj[n2].push_back(make_pair(n1, weight));
    }
 
    priority_queue<tuple<int,int, int>, vector<tuple<int,int, int>>, greater<tuple<int, int, int>>> minHeap; 
    for (vector<int> edge : edges) {
        int n1 = edge[0], n2 = edge[1], weight = edge[2];
        minHeap.push({weight, n1, n2});
    }
    
    UnionFind unionFind(n);
    vector<pair<int, int>> mst;
    while (mst.size() < n - 1) {
        tuple<int, int, int> cur = minHeap.top();
        minHeap.pop();
        int w1 = get<0>(cur), n1 = get<1>(cur), n2 = get<2>(cur);
 
        if (!unionFind.union(n1, n2)) {
            continue;
        }
        mst.push_back({n1, n2});
    }
    return mst;
}