/*
https://blog.csdn.net/sugarbliss/article/details/86495945?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169977002316800215045285%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=169977002316800215045285&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-86495945-null-null.142^v96^pc_search_result_base2&utm_term=%E9%93%BE%E5%BC%8F%E5%89%8D%E5%90%91%E6%98%9F&spm=1018.2226.3001.4187
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1005; // 点数最大值
int n, m, cnt; // n个点,m条边
struct Edge
{
int to, w, next; // 终点,边权,同起点的上一条边的编号
} edge[maxn]; // 边集
int head[maxn]; // head[i],表示以i为起点的第一条边在边集数组的位置(编号)
void init() // 初始化
{
for (int i = 0; i <= n; i++)
head[i] = -1;
cnt = 0;
}
// 编号从0开始
void add_edge(int u, int v, int w) // 加边,u起点,v终点,w边权
{
edge[cnt].to = v; // 终点
edge[cnt].w = w; // 权值
edge[cnt].next = head[u]; // 以u为起点上一条边的编号,也就是与这个边起点相同的上一条边的编号
head[u] = cnt++; // 更新以u为起点上一条边的编号
}
int main()
{
cin >> n >> m;
int u, v, w;
init(); // 初始化
for (int i = 1; i <= m; i++) // 输入m条边
{
cin >> u >> v >> w;
add_edge(u, v, w); // 加边
/*
加双向边
add_edge(u, v, w);
add_edge(v, u, w);
*/
}
/*
我们初始化head为-1,所以找到你最后一个边(也就是以 i 为起点的第一条边)时,你的edge[j].next为 -1做为终止条件
*/
for (int i = 1; i <= n; i++) // n个起点
{
cout << i << endl;
for (int j = head[i]; j != -1; j = edge[j].next) // 遍历以i为起点的边
{
cout << i << " " << edge[j].to << " " << edge[j].w << endl;
}
cout << endl;
}
return 0;
}
/*
5 7
1 2 1
2 3 2
3 4 3
1 3 4
4 1 5
1 5 6
4 5 7
*/