// verification-helper: PROBLEM https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/2/GRL_2_A
#include "src/graph/kruskal.hpp"
#include <iostream>
using namespace std;
int main() {
int v, e;
cin >> v >> e;
Kruskal<int> k(v);
for (int i = 0; i < e; ++i) {
int a, b, c;
cin >> a >> b >> c;
k.add_edge(a, b, c);
}
cout << k.mst_cost() << endl;
return 0;
}
#line 1 "test/graph/kruskal/aoj_grl_2_a.test.cpp"
// verification-helper: PROBLEM https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/2/GRL_2_A
#line 1 "src/graph/kruskal.hpp"
#line 1 "src/datastructure/disjoint_set_union.hpp"
#include <numeric>
#include <utility>
#include <vector>
class DisjointSetUnion {
private:
std::vector<int> rank, size, p;
int num{};
public:
DisjointSetUnion(int n) : rank(n), size(n, 1), p(n), num(n) {
std::iota(p.begin(), p.end(), 0);
}
bool same(int x, int y) { return root(x) == root(y); }
void unite(int x, int y) {
x = root(x);
y = root(y);
if (x == y) return;
--num;
if (rank[x] < rank[y]) std::swap(x, y);
if (rank[x] == rank[y]) ++rank[x];
p[y] = x;
size[x] += size[y];
}
int root(int x) { return p[x] == x ? x : p[x] = root(p[x]); }
int get_size(int x) { return size[root(x)]; }
[[nodiscard]] int forest_size() const { return num; }
};
#line 5 "src/graph/kruskal.hpp"
#include <algorithm>
#line 8 "src/graph/kruskal.hpp"
template<class T>
class Kruskal {
private:
struct Edge {
int from, to;
T cost;
Edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
bool operator<(Edge const &a) { return cost < a.cost; }
};
int n;
std::vector<Edge> g;
public:
Kruskal(int n) : n(n) {}
void add_edge(int from, int to, T cost) { g.emplace_back(from, to, cost); }
T mst_cost() {
T cost = 0;
std::sort(g.begin(), g.end());
DisjointSetUnion dsu(n);
cost = 0;
for (Edge const &e : g) {
if (!dsu.same(e.from, e.to)) {
cost += e.cost;
dsu.unite(e.from, e.to);
}
}
return cost;
}
};
#line 4 "test/graph/kruskal/aoj_grl_2_a.test.cpp"
#include <iostream>
using namespace std;
int main() {
int v, e;
cin >> v >> e;
Kruskal<int> k(v);
for (int i = 0; i < e; ++i) {
int a, b, c;
cin >> a >> b >> c;
k.add_edge(a, b, c);
}
cout << k.mst_cost() << endl;
return 0;
}