#include <fstream>
#include <algorithm>
using namespace std;
ifstream fin("apm.in");
ofstream fout("apm.out");
const int MMax = 400000;
const int NMax = 200000;
struct Edge
{
int x,y,cost;
}E[MMax + 5];
int N,M,K,Sol;
int TT[NMax + 5],Idx[NMax + 5],R[NMax + 5];
bool Compare(Edge A, Edge B)
{
return A.cost <= B.cost;
}
void Read()
{
fin >> N >> M;
for(int i = 1; i <= M; ++i)
fin >> E[i].x>>E[i].y>>E[i].cost;
sort(E+1,E+M+1,Compare);
}
int Root (int x)
{
while(x!=TT[x])
{
x = TT[x];
}
return x;
}
void Unite(int x, int y)
{
if(R[x] < R[y])
TT[x] = y;
if(R[x] > R[y])
TT[y] = x;
if(R[x] == R[y])
{
TT[x] = y;
R[y]++;
}
}
void Solve()
{
for(int i = 1; i <= N; ++i)
TT[i] = i;
for(int i = 1; i <= M; ++i)
{
int a = E[i].x, b = E[i].y, c = E[i].cost;
if(Root(a) != Root(b))
{
Unite(Root(a), Root(b));
Sol += c;
Idx[++K] = i;
}
}
}
void Print()
{
fout << Sol << "\n";
fout << N-1 << "\n";
for(int i = 1; i <= K; ++i)
{
fout << E[Idx[i]].x << " " << E[Idx[i]].y << "\n";
}
}
int main()
{
Read();
Solve();
Print();
return 0;
}