// Arbre de recouvrement minimal (Minimum Spanning Tree) // Algorithme de Kruskal // https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/ #include using namespace std; class DSU // Disjoint Set Data { private: vector parent, rank; public: DSU(int n) // constructeur { parent.resize(n); rank.resize(n); for(int i = 0; i < n; i++) { parent[i] = i; rank[i] = 1; } } // DSU() int find(int i) { return (parent[i] == i) ? i : (parent[i] = find(parent[i])); } // find() void unite(int x, int y) { int s1 = find(x), s2 = find(y); if(s1 != s2) { if(rank[s1] < rank[s2]) parent[s1] = s2; else if(rank[s1] > rank[s2]) parent[s2] = s1; else parent[s2] = s1, rank[s1]++; } } // unite() }; // classe DSU bool comparator(vector &a,vector &b) { if(a[2] <= b[2]) return true; return false; } // comparator() // Algorithme de Kruskal int kruskalsMST(int V, vector> &edges) { // Trier les arêtes selon leurs poids sort(edges.begin(), edges.end(), comparator); DSU dsu(V); int cost = 0, count = 0; for(auto &e : edges) // pour chaque arête en ordre { int x = e[0], y = e[1], w = e[2]; // Vérifier qu'il n'y a pas de cycle if(dsu.find(x) != dsu.find(y)) { dsu.unite(x, y); cost += w; if(++count == V - 1) break; } } return cost; } // kruskalMST() // Programme principal int main() { int n = 0; cin >> n; // sommets vector> graph(n, vector(n, 0)); // matrice d'adjacences for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) cin >> graph[i][j]; vector> edges; // {u, v, w} for(int i = 0; i < n; i++) for(int j = i + 1; j < n; j++) if(graph[i][j] != 0) edges.push_back({i, j, graph[i][j]}); /*for(auto e : edges) cout << e[0] << " -> " << e[1] << " : " << e[2] << '\n';*/ cout << kruskalsMST(n, edges) << '\n'; return 0; } // main()