// poj1861 最小生成树 prim & kruskal
//
// 一个水题,为的仅仅是回味一下模板。日后好有个照顾不是 #include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <iostream> using namespace std; const int MAX_N = 1008;
const int INF = 0x3f3f3f3f;
int g[MAX_N][MAX_N];
int n,m;
int cnt;
int mx;
int d[MAX_N];
bool vis[MAX_N];
int pre[MAX_N];
struct edge{
int from;
int to;
int w; edge(){ } edge(int from,int to,int w): from(from),to(to),w(w){ } };
edge edges[MAX_N * 15]; bool cmp(edge a,edge b){
return a.w < b.w;
} void print1(){
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++)
printf("%d ",g[i][j]);
puts("");
} } void input1(){
int u,v,cost; for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++){
g[i][j] = INF;
if (i == j)
g[i][j] = 0;
} for (int i=0;i<m;i++){
scanf("%d%d%d",&u,&v,&cost);
g[u][v] = g[v][u] = cost; } // print1(); for (int i=1;i<=n;i++){
pre[i] = 1;
} cnt = 0; } int fa[MAX_N];
int height[MAX_N];
void input2(){
int u,v,cost;
for (int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&cost);
edges[i] = edge(u,v,cost);
}
for (int i=1;i<=n;i++){
fa[i] = i;
height[i] = 0;
}
sort(edges+1,edges+m+1,cmp); } int getf(int x){
if (x==fa[x])
return x;
return fa[x] = getf(fa[x]);
} void kruskal(){
int cnt = 0;
int mx = 0;
for (int i=1;i<=m;i++){
int x = getf(edges[i].from);
int y = getf(edges[i].to);
if (x==y)
continue;
if (height[x] < height[y]){
fa[x] = y;
}else {
fa[y] = x;
if (height[x]==height[y])
height[x]++;
}
mx = max(mx,edges[i].w);
edges[cnt++] = edges[i];
}
printf("%d\n",mx);
printf("%d\n",cnt);
for (int i=0;i<cnt;i++){
printf("%d %d\n",edges[i].from,edges[i].to);
}
} void prim(){
for (int i=1;i<=n;i++)
d[i] = g[1][i];
d[1] = 0;
for (int i=1;i<=n;i++){
vis[i] = 0;
}
vis[1] = 1;
mx = 0;
for (int i=1;i<=n;i++){
int k = -1;
for (int j=1;j<=n;j++){
if (!vis[j] && (k == -1 || d[k] > d[j])){
k = j;
}
}
if (k==-1)
break;
vis[k]++;
mx = max(mx,d[k]);
edges[cnt++] = edge(k,pre[k],d[k]);
for (int j=1;j<=n;j++){
if (!vis[j] && g[k][j]!= INF &&d[j] > g[k][j]){
d[j] = g[k][j];
pre[j] = k;
}
} } } void print(){
printf("%d\n",mx);
printf("%d\n",cnt);
for (int i=0;i<cnt;i++){
printf("%d %d\n",edges[i].from,edges[i].to);
}
} void solve(){
//prim();
kruskal();
//print();
} int main(){ freopen("1.txt","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF){ //input1();
input2();
solve();
}
}