// Slower C++ solution:
#include<stdio.h>

#include<algorithm>

#include<iostream>

using namespace  std;

int fa[100010];

int n,m;

struct edge{

	int x,y,w;

	edge(int x=0,int y=0 ,int w=0 ):x(x),y(y),w(w){

	}

}a[100010];

int getfa(int x){

	if(x==fa[x]) return x;

	else return getfa(fa[x]);

}

bool cmp(edge a,edge b){

	return a.w<b.w;

}

int f(){

	int ans=0;

	sort(a,a+m,cmp);

	int cnt=n;

	for(int i=0;i<n;i++) fa[i]=i;

	for(int i=0;i<m;i++){

		int f1=getfa(a[i].x),

		f2=getfa(a[i].y);

		if(f1!=f2){

			ans+=a[i].w;

			cnt--;

			fa[f1]=f2;

			if(cnt==1) break;

		}

	}

	return ans;

}

int main(){

	scanf("%d%d",&n,&m);

	for(int i=0;i<m;i++){

		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);

	}

	printf("%d\n",f());

	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 2.141571720741721x):
#define _CRT_SECURE_NO_WARNINGS

#include "bits/stdc++.h"



#define PB push_back

#define PF push_front

#define LB lower_bound

#define UB upper_bound

#define fr(x) freopen(x,"r",stdin)

#define fw(x) freopen(x,"w",stdout)

#define iout(x) printf("%d\n",x)

#define lout(x) printf("%lld\n",x)

#define REP(x,l,u) for(ll x = l;x<u;x++)

#define RREP(x,l,u) for(ll x = l;x>=u;x--)

#define complete_unique(a) a.erase(unique(a.begin(),a.end()),a.end())

#define mst(x,a) memset(x,a,sizeof(x))

#define all(a) a.begin(),a.end()

#define PII pair<int,int>

#define PLL pair<ll,ll>

#define MP make_pair

#define sqr(x) ((x)*(x))

#define lowbit(x) ((x)&(-(x)))

#define lson (ind<<1)

#define rson (ind<<1|1)

#define se second

#define fi first

#define sz(x) ((int)x.size())

#define EX0 exit(0);



typedef  long long ll;

typedef unsigned long long ull;

typedef double db;

typedef long double ld;

using namespace std;

typedef vector<ll> VLL;

typedef vector<int> VI;

const int block_size = 320;

typedef complex<ll> point;

const ll mod = 1e9 + 7;

const ll inf = 1e9 + 7;

const ld eps = 1e-9;

const db PI = atan(1) * 4;



template<typename T, typename S>inline bool upmin(T&a, const S&b) { return a > b ? a = b, 1 : 0; }

template<typename T, typename S>inline bool upmax(T&a, const S&b) { return a < b ? a = b, 1 : 0; }



ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a%b); }

ll pow(ll a, ll b) {

    if (b == 0) {

        return 1;

    }

    if (b == 1) {

        return a;

    }

    ll ans = pow(a, b / 2);

    ans *= ans;

    ans *= b % 2 == 1 ? a : 1;

    return ans;

}



namespace SOLVE {

    struct edge {

        ll v1, v2, weight;

    };

    

    VI id;

    

    ll parent(ll a) {

        if (id[a] == a) {

            return a;

        }

        id[a] = parent(id[a]);

        return id[a];

    }

    

    void unite(ll a, ll b) {

        id[parent(a)] = parent(b);

    }

    

    int query(ll a, ll b) {

        return (parent(a) == parent(b));

    }

    

    bool comp(edge a, edge b) {

        return a.weight < b.weight;

    }

    

    void main() {

        ll V, E, a, b, c;

        cin >> V >> E;

        

        vector<edge> edges;

        

        REP(i, 0, E) {

            cin >> a >> b >> c;

            edge x;

            x.v1 = a;

            x.v2 = b;

            x.weight = c;

            edges.push_back(x);

        }

        

        sort(edges.begin(), edges.end(), comp);

        

        id.resize(V);

        REP(i, 0, V) {

            id[i] = i;

        }

        

        ll ans = 0;

        for(int i = 0;i<E;i++){

            const edge&e = edges[i];

            if (!query(e.v1, e.v2)) {

                // join them

                unite(e.v1, e.v2);

                // cout << e.v1 << ' ' << e.v2 << ' ' << e.weight << endl;

                ans += e.weight;

                

            }

        }

        cout << ans << endl;

    }

}





signed main() {

    ios_base::sync_with_stdio(false);

    cin.tie(NULL);

    

    int t;

    //    in(t);

    t = 1;

    while (t--) {

        SOLVE::main();

        

    }

    

    return 0;

}