#include <bits/stdc++.h>
#include<fstream>
using namespace std;
ifstream fin("apm.in");
ofstream fout("apm.out");
int tata[100002], h[100002];
int getroot(int x)
{
int root=x;
while(tata[root]!=root)
root=tata[root];
while(x!=tata[x]) //x!=root
{
int tx=tata[x];
tata[x]=root;
x=tx;
}
return root;
}
void unite(int x, int y)
{
x=getroot(x);
y=getroot(y);
if(h[x]<h[y])
tata[x]=y;
else if(h[x]==h[y]){
tata[x]=y;
h[y]++;}
else
tata[y]=x;
}
vector <pair <int, pair <int, int>>> edges;
vector <pair <int, pair <int, int>>> chosenEdges;
int main()
{
int n, m, x, y, op;
int tot=0;
fin>>n>>m;
for(int i=1;i<=n;i++)
{
tata[i]=i;
h[i]=1;
}
for (int i = 1; i <= m; i++) {
int x, y, cost;
fin >> x >> y >> cost;
edges.push_back(make_pair(cost, make_pair(x, y)));
}
sort(edges.begin(), edges.end());
for (auto edge: edges) {
int x = edge.second.first;
int y = edge.second.second;
int cost = edge.first;
if (getroot(x) == getroot(y))
continue;
unite(x, y);
chosenEdges.push_back(make_pair(cost, make_pair(x, y)));
tot += cost;
}
fout << tot << '\n';
fout << chosenEdges.size() << '\n';
for (auto edge: chosenEdges) {
fout << edge.second.second << ' ' << edge.second.first << '\n';
}
return 0;
}