/*
算法概述:假设N=(V,E)是连通图 ,TE是N上的最小生成树中的边集合。算法从定点
集合U={u0}(u0属于v),边集合TE开始为空,在u属于集合U,v 属于集合V-U的边(u,v)属于
E中找一条代价最小边
*/
#include < stdio.h >
#include < limits.h >
#define MAXN 1002
typedef struct {
int Vnum;
int Arcs[MAXN][MAXN];
} Graph;
Graph g;
int tree[ 1003 ][ 4 ];
void create_graph( int vn, int en) {
int i,j,n;
int v1,v2,w;
g.Vnum=vn;
for(i=1;i<=vn;i++)
for(j=1;j<=vn;j++)
g.Arcs[i][j]=INT_MAX;
for(i=1;i<=en;i++)
{
scanf("%d%d%d",&v1,&v2,&w);
//if(e[a][b]<INT_MAX && e[a][b]<c)continue;
g.Arcs[v1][v2]=g.Arcs[v2][v1]=w;
}
}
void prim() {
int i,j,k,m,min,c,vn;
int V[MAXN],lowcost[MAXN];
vn=g.Vnum;
for(i=1;i<=vn;i++){
V[i]=1;//设初始为1表示 tree中开始只有点1
lowcost[i]=g.Arcs[1][i];//i到V[i]的权值
}
V[1]=0;//点1不再是要考虑的点
for(i=1;i<vn;i++)
{
min=INT_MAX;
for(m=1;m<=vn;m++)
if(V[m]!=0&&lowcost[m]<min)
{
min=lowcost[m];
k=m;
}
tree[i][1]=V[k];
tree[i][2]=k;
tree[i][3]=min;
V[k]=0;//点k不再是要考虑的点
for(j=1;j<=vn;j++)//由于tree新加入k点,试图找出tree中点到非tree中点更小的权值
if(V[j]!=0 && g.Arcs[k][j]<INT_MAX && g.Arcs[k][j]<lowcost[j]){
lowcost[j]=g.Arcs[k][j];
V[j]=k;
}
}
}
int main() {
int vn,en,value,i,j;
while(scanf("%d%d",&vn,&en)!=EOF)
{
create_graph(vn,en);
prim();
for(j=1;j<vn;j++)
printf("%d %d %d ",tree[j][1],tree[j][2],tree[j][3]);
}
}
/*
Input:
6 10
1 2 6
1 3 1
1 4 5
2 3 5
2 5 3
3 4 5
3 5 6
3 6 4
4 6 2
5 6 6
Output:
1 3 1
3 6 4
6 4 2
3 2 5
2 5 3
*/