#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<stack>
#include<set>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#define ll __int64
#define lll unsigned long long
#define MAX 1000009
#define eps 1e-8
#define INF 0xfffffff
#define mod 1000000007
using namespace std;
/*
题意:
解法:Kruskal模板,这里的使用赋权值的并查集。
*/
struct edge
{
int x;
int y;
int z;
} num[MAX];
bool cmp(edge x,edge y)
{
return x.z<y.z;
}
int N,M;//N个点,M条边
int father[MAX];
int _max;
int sum;
int ok[MAX];
int kk;
//void init()
//{
// for(int i = 1; i<=N; i++)
// father[i] = -1;
//}
//int Find(int x)
//{
// if(father[x]<0)
// return x;
// else
// return father[x]=Find(father[x]);
//}
//void Union(int x,int y)
//{
// int xx=Find(x);
// int yy=Find(y);
// if( xx == yy ) return ;
// if( father[xx] < father[yy] )
// {
// father[xx] += father[yy];
// father[yy] = xx;
// }
// else
// {
// father[yy] += father[xx];
// father[xx] = yy;
// }
//}
int Find(int x)
{
if (father[x]!=x)
father[x]=Find(father[x]);
return father[x];
}
void init()
{
for(int i = 1; i<=N; i++)
father[i] = i;
}
void Union(int x,int y)
{
int xx=Find(x);
int yy=Find(y);
if( xx == yy ) return ;
father[yy] = xx;
}
void Krusal()
{
kk = 0;
init();
for(int i = 0; i<M; i++)
{
//cout<<"check"<<endl;
int xx = num[i].x;
int yy = num[i].y;
if(Find(xx)!=Find(yy))
{
//cout<<xx<<" "<<yy<<endl;
ok[kk++] = i;
if(num[i].z>_max)
_max = num[i].z;
Union(xx,yy);
}
}
}
int main()
{
int a,b,c;
while(~scanf("%d%d",&N,&M))
{
for(int i = 0; i<M; i++)
{
scanf("%d%d%d",&num[i].x,&num[i].y,&num[i].z);
}
sort(num,num+M,cmp);
_max = - INF;
sum = 0;
Krusal();
printf("%d\n",_max);
printf("%d\n",kk);
for(int i = 0; i<kk; i++)
{
printf("%d %d\n",num[ok[i]].x,num[ok[i]].y);
}
}
return 0;
}
#include<cstdio>
#include<string.h>
#include<string>
#include<stack>
#include<set>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#define ll __int64
#define lll unsigned long long
#define MAX 1000009
#define eps 1e-8
#define INF 0xfffffff
#define mod 1000000007
using namespace std;
/*
题意:
解法:Kruskal模板,这里的使用赋权值的并查集。
*/
struct edge
{
int x;
int y;
int z;
} num[MAX];
bool cmp(edge x,edge y)
{
return x.z<y.z;
}
int N,M;//N个点,M条边
int father[MAX];
int _max;
int sum;
int ok[MAX];
int kk;
//void init()
//{
// for(int i = 1; i<=N; i++)
// father[i] = -1;
//}
//int Find(int x)
//{
// if(father[x]<0)
// return x;
// else
// return father[x]=Find(father[x]);
//}
//void Union(int x,int y)
//{
// int xx=Find(x);
// int yy=Find(y);
// if( xx == yy ) return ;
// if( father[xx] < father[yy] )
// {
// father[xx] += father[yy];
// father[yy] = xx;
// }
// else
// {
// father[yy] += father[xx];
// father[xx] = yy;
// }
//}
int Find(int x)
{
if (father[x]!=x)
father[x]=Find(father[x]);
return father[x];
}
void init()
{
for(int i = 1; i<=N; i++)
father[i] = i;
}
void Union(int x,int y)
{
int xx=Find(x);
int yy=Find(y);
if( xx == yy ) return ;
father[yy] = xx;
}
void Krusal()
{
kk = 0;
init();
for(int i = 0; i<M; i++)
{
//cout<<"check"<<endl;
int xx = num[i].x;
int yy = num[i].y;
if(Find(xx)!=Find(yy))
{
//cout<<xx<<" "<<yy<<endl;
ok[kk++] = i;
if(num[i].z>_max)
_max = num[i].z;
Union(xx,yy);
}
}
}
int main()
{
int a,b,c;
while(~scanf("%d%d",&N,&M))
{
for(int i = 0; i<M; i++)
{
scanf("%d%d%d",&num[i].x,&num[i].y,&num[i].z);
}
sort(num,num+M,cmp);
_max = - INF;
sum = 0;
Krusal();
printf("%d\n",_max);
printf("%d\n",kk);
for(int i = 0; i<kk; i++)
{
printf("%d %d\n",num[ok[i]].x,num[ok[i]].y);
}
}
return 0;
}