// Arup Guha
// 6/14/2026
// Generic implementation of Prim's Algorithm.

using namespace std;

#include <bits/stdc++.h>

struct edge {

    int u;
    int v;
    int w;

    // Here, we define less than, which the priority queue uses.
    // pq's are max queues in c++, so this is pretty weird.
    bool operator<(const edge& other) const {
        return w >= other.w;
    }
};

int prims(vector<vector<edge>>& g, int v);

int main() {

    /*** Input format: first line, n and e, # of vertices, then edges.
                       Next e lines contain 3 integers:
                       u v w, edge connecting u and v, 1-based indexes
                              w is weight
    ***/

    // Get number of vertices and edges.
    int n, e;
    cin >> n >> e;

    // Make the graph.
    vector<vector<edge>> graph(n);

    // Add each edge into the graph.
    for (int i=0; i<e; i++) {

        // Read in, make 0 based.
        struct edge e1, e2;
        cin >> e1.u >> e1.v >> e1.w; e1.u--; e1.v--;

        // Add both edges.
        e2.u = e1.v; e2.v = e1.u; e2.w = e1.w;
        graph[e1.u].push_back(e1);
        graph[e2.u].push_back(e2);
    }

    // Output MST cost or -1 if there's no MST.
    cout << prims(graph, 0) << endl;
    return 0;
}

// Returns the MST of the graph g, starting Prim's algorithm at vertex v.
int prims(vector<vector<edge>>& g, int v) {

    // Set up prims.
    int n = g.size();

    // Store vertices connected.
    vector<bool> used(n, false);

    // Priority Queue of edges to consider, put in edges from v.
    priority_queue<edge> pq;
    used[v] = true;
    for (auto e: g[v])
        pq.push(e);

    // Bookkeeping.
    int numE = 0;
    int cost = 0;

    // We'll handle the disconnected case in the loop.
    while (numE < n-1) {

        // Indicates no MST (not connected).
        if (pq.size() == 0) return -1;

        // Get the next edge.
        edge cur = pq.top(); pq.pop();

        // Doesn't help us get anywhere new.
        if (used[cur.u] && used[cur.v]) continue;

        // Added vertex.
        int nV = !used[cur.u] ? cur.u : cur.v;
        numE++;
        used[nV] = true;
        cost += cur.w;

        // Add edges from this vertex.
        for (auto e: g[nV])
            pq.push(e);
    }

    // Ta da!
    return cost;
}
