import java.util.Scanner;
public class Prim_MinTree {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// n是顶点的个数,m是边的个数
int n = sc.nextInt(), m = sc.nextInt();
int[][] uvw = new int[n + 1][n + 1];// 存放顶点与顶点间的权值,一个邻接矩阵
// 初始化
for (int i = 1; i < n + 1; i++) {
for (int j = 1; j < n + 1; j++) {
if (i != j)
uvw[i][j] = Integer.MAX_VALUE;// 用于代表顶点i与顶点j之间不相连
}
}
for (int i = 0; i < m; i++) {
int u = sc.nextInt(), v = sc.nextInt(), w = sc.nextInt();
uvw[u][v] = w;
uvw[v][u] = w;
}
int lowcost[] = new int[n + 1];// 临时数组,先存邻接矩阵的第一行数据,在下面就知道它的作用了
// 初始化,先存第一组数据
for (int i = 1; i < lowcost.length; i++)
lowcost[i] = uvw[1][i];
int adjvex[] = new int[n + 1];// 存放相关顶点的下标的
// 比如,初始化都是1,1就表示就是i顶点和顶点1都相连,如果adjvex[i]=3,表示顶点i与顶点3相连
for (int i = 1; i < adjvex.length; i++)
adjvex[i] = 1;
// 开始种最小生成树
for (int i = 1; i < n + 1; i++) {
int min = Integer.MAX_VALUE;
int k = 1;
// 在lowcost数组内找出最小的那个权值,并获取到角标,lowcost就是记录每一组数据的数组
for (int j = 1; j < lowcost.length; j++) {
if (lowcost[j] != 0 && lowcost[j] < min) {
min = lowcost[j];
k = j;// 获得最小权值的角标
}
}
if (adjvex[k] == k)// 最小生成树生成完,当出现顶点与自己相连这种情况,就代表完成了
break;
System.out.print("(" + adjvex[k] + "," + k + ") ");// adjvex[k]与k相连
lowcost[k] = 0;// 标记该顶点完成任务
// 这里是更新lowcost数组,邻接矩阵的第k行数据与lowcost数组进行比较
for (int j = 1; j < n + 1; j++) {
if (lowcost[j] != 0 && uvw[k][j] < lowcost[j]) {
lowcost[j] = uvw[k][j];
adjvex[j] = k;
}
}
}
sc.close();
}
}