#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
const int INF = 0x3f3f3f3f;
typedef struct Edge{
int to; //终点
int dis; //花费
bool operator < (const Edge& e)const {
return dis > e.dis;
}
};
vector<Edge> Map[maxn];
bool vis[maxn];
int d[maxn];
int cost[maxn];
void dijkstra()
{
memset(vis, 0, sizeof(vis));
memset(d, 0x3f, sizeof(d));
memset(cost, 0x3f, sizeof(cost));
d[1] = cost[1] = 0;
Edge e;
e.to = 1; e.dis = 0;
priority_queue<Edge> p_q;
p_q.push(e);
while(!p_q.empty()){
e = p_q.top();
p_q.pop();
int v = e.to;
if(vis[v])
continue;
vis[v] = 1;
for(int i = 0; i < Map[v].size(); i++){
e = Map[v][i];
if(d[e.to] > d[v] + e.dis){ //到达e.to的路径非最短路径
d[e.to] = d[v] + e.dis;
cost[e.to] = e.dis;
Edge ee;
ee.to = e.to, ee.dis = d[e.to];
p_q.push(ee);
}
if(d[e.to]==d[v]+e.dis && cost[e.to] > e.dis) //到达e.to的路径是最短路径,但并不是最小生成树
cost[e.to] = e.dis;
}
}
}
int main()
{
int n, m;
cin >> n >> m;
for(int i = 0; i < m; i++){
int v1, v2, c;
cin >> v1 >> v2 >> c;
Edge e1, e2;
e1.to = v2, e1.dis = c;
e2.to = v1, e2.dis = c;
Map[v1].push_back(e1);
Map[v2].push_back(e2);
}
dijkstra();
int ans = 0;
for(int i = 1; i <= n; i++){
ans += cost[i];
}
cout << ans << endl;
return 0;
}