#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <climits>
#include <stdio.h>
using namespace std;

struct HeapNode
{
	HeapNode(): v(0), key(INT_MAX) {
	};
	HeapNode(int v, int key): v(v), key(key) {
	};
	int v;
	int key;
};

class MinHeap {
private:
	vector<HeapNode> vHeap;
	vector<int> vPos;

public:
	MinHeap(int V): vHeap(V+1), vPos(V) {
		for (int i = 1; i <= V; i++) {
			vHeap[i].v = i-1;
			vPos[i-1] = i;
		}
	}

	void percolateDown(int idx) {
		int smallest = idx;
		int leftChild = 2*idx;
		int rightChild = 2*idx + 1;

		if(leftChild < vHeap.size() && vHeap[leftChild].key < vHeap[smallest].key) {
			smallest = leftChild;
		}

		if(rightChild < vHeap.size() && vHeap[rightChild].key < vHeap[smallest].key) {
			smallest = rightChild;
		}
		//cout << "percolateDown " << idx << " " << smallest <<endl;
		if (smallest != idx) {
			HeapNode tmpNode = vHeap[idx];
			
			vPos[vHeap[idx].v] = smallest;
			vPos[vHeap[smallest].v] = idx;

			vHeap[idx] = vHeap[smallest];
			vHeap[smallest] = tmpNode;

			percolateDown(smallest);
		}

	}

	HeapNode extractMin() {
		HeapNode result = vHeap[1];
		//cout << "result " << result.v << " " << result.key << endl;

		int last = vHeap.size() - 1;
		vPos[result.v] = last;
		vPos[vHeap[last].v] = 1;
		vHeap[1] = vHeap[last];

		vHeap.pop_back();
		//printf("extractMin %d\n", result.v);
		percolateDown(1);
		return result;
	}

	void decreaseKey(int v, int key) {
		int i = vPos[v];

		//printf("decreaseKey %d pos %d\n", v, i);

		vHeap[i].key = key;

		while (i > 1 && vHeap[i].key < vHeap[i/2].key) {
			//printf("decreaseKey exchange %d key %d %d key %d \n", i, vHeap[i].key, i/2, vHeap[i/2].key);
			HeapNode tmpNode = vHeap[i];
			
			vPos[vHeap[i].v] = i/2;
			vPos[vHeap[i/2].v] = i;

			vHeap[i] = vHeap[i/2];
			vHeap[i/2] = tmpNode;
			i=i/2;
		}
	}

	bool isInHeap(int v) {
		return vPos[v] < vHeap.size();
	}

	int getWeight(int v) {
		//cout << "getWeight " << v << " pos "<< vPos[v] << " key " << vHeap[vPos[v]].key << endl; 
		return vHeap[vPos[v]].key;
	}
};

class Graph {
private:
	struct AdjNode {
		AdjNode(int dst, int weight): dst(dst), weight(weight) {
		};
		AdjNode(): dst(), weight() {
		};
		int dst;
		int weight;
	};
	vector<list<AdjNode> > vAdj;

public:
	Graph(int V):vAdj(V) {
	}

	void addEdge(int src, int dst, int weight) {
		AdjNode adjNode(dst, weight);
		vAdj[src].push_back(adjNode);
		vAdj[dst].push_back(AdjNode(src, weight));
	};

	int prim() {
		int result = 0;
		int V = vAdj.size();
		vector<AdjNode> parent(vAdj.size());
		MinHeap vertexHeap(vAdj.size());

		vertexHeap.decreaseKey(0, 0);
		parent[0].dst = -1;
		parent[0].weight = 0;

		for (int i = 0; i < V - 1; i++) {
			HeapNode node = vertexHeap.extractMin();
			int v = node.v;
			list<AdjNode>::iterator it = vAdj[v].begin();
			for (it = vAdj[v].begin(); it != vAdj[v].end(); it++) {
					int u = it->dst;
					int weight = it->weight;
					if (vertexHeap.isInHeap(u) && weight < vertexHeap.getWeight(u)) {
						//printf("decreaseKey %d %d\n", u, weight);
						vertexHeap.decreaseKey(u, weight);
						parent[u].dst = v;
						parent[u].weight = weight;
					}
			}
		}

		for (int i = 1; i < vAdj.size(); i++) {
			//printf("%d - %d weight %d\n", parent[i].dst, i, parent[i].weight);
			result += parent[i].weight;
		}

		return result;
	}
};

int main() {
	 // Let us create the graph given in above fugure
	int V, E;
	cin >> V >> E;
	Graph g(V);

	for(int i = 0; i < E; i++) {
		int src, dst, weight;
		cin >> src >> dst >> weight;
		g.addEdge(src ,dst, weight);
	}

    cout << g.prim() << endl;
 
    return 0;
}

Measured memory_bytes: 7744