#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cassert>

using namespace std;

struct edge { int to, cost; };
typedef pair<int, int> P;

const int MAX_V = 10000;
const int INF = 1 << 28;

int V;
vector<edge> G[MAX_V];
int d[MAX_V];

int prim(){
	int res = 0;
	priority_queue<P, vector<P>, greater<P> > que;
	fill(d, d + V, INF);
	d[0] = 0;
	que.push(P(0, 0));
	while(!que.empty()){
		P p = que.top(); que.pop();
		int v = p.second;
		if(d[v] < p.first) continue;
		res += p.first;
		for(int i=0;i<G[v].size();i++){
			edge e = G[v][i];
			if(d[e.to] > e.cost){
				d[e.to] = e.cost;
				que.push(P(e.cost, e.to));
			}
		}
	}
	return res;
}

int main(){
	int E;
	cin >> V >> E;
	for(int i=0;i<E;i++){
		int s, t, w;
		cin >> s >> t >> w;
		assert(0 <= s && s < V);
		assert(0 <= t && t < V);
		G[s].push_back((edge){t, w});
		G[t].push_back((edge){s, w});
	}
	cout << prim() << endl;
	return 0;
}