The German University in Cairo (GUC) dorm houses are numbered from 1 to *n*. Underground water pipes connect these houses together. Each pipe has certain direction (water can flow only in this direction and not vice versa), and diameter (which characterizes the maximal amount of water it can handle).

For each house, there is at most one pipe going into it and at most one pipe going out of it. With the new semester starting, GUC student and dorm resident, Lulu, wants to install tanks and taps at the dorms. For every house with an outgoing water pipe and without an incoming water pipe, Lulu should install a water tank at that house. For every house with an incoming water pipe and without an outgoing water pipe, Lulu should install a water tap at that house. Each tank house will convey water to all houses that have a sequence of pipes from the tank to it. Accordingly, each tap house will receive water originating from some tank house.

In order to avoid pipes from bursting one week later (like what happened last semester), Lulu also has to consider the diameter of the pipes. The amount of water each tank conveys should not exceed the diameter of the pipes connecting a tank to its corresponding tap. Lulu wants to find the maximal amount of water that can be safely conveyed from each tank to its corresponding tap.
The first line contains two space-separated integers *n* and *p* (1 ≤ *n* ≤ 1000, 0 ≤ *p* ≤ *n*) — the number of houses and the number of pipes correspondingly. 

Then *p* lines follow — the description of *p* pipes. The *i*-th line contains three integers *a*<sub class="lower-index">*i*</sub> *b*<sub class="lower-index">*i*</sub> *d*<sub class="lower-index">*i*</sub>, indicating a pipe of diameter *d*<sub class="lower-index">*i*</sub> going from house *a*<sub class="lower-index">*i*</sub> to house *b*<sub class="lower-index">*i*</sub> (1 ≤ *a*<sub class="lower-index">*i*</sub>, *b*<sub class="lower-index">*i*</sub> ≤ *n*, *a*<sub class="lower-index">*i*</sub> ≠ *b*<sub class="lower-index">*i*</sub>, 1 ≤ *d*<sub class="lower-index">*i*</sub> ≤ 10<sup class="upper-index">6</sup>).

It is guaranteed that for each house there is at most one pipe going into it and at most one pipe going out of it.
3 2
1 2 10
2 3 20
1
1 3 10
3 3
1 2 20
2 3 10
3 1 5
0
4 2
1 2 60
3 4 50
2
1 2 60
3 4 50
10 10
10 3 70
1 9 98
9 10 67
5 2 78
8 6 71
4 8 95
7 1 10
2 5 73
6 7 94
3 4 23
0
7 5
3 2 26
4 6 84
6 3 82
5 1 57
1 7 34
2
4 2 26
5 7 34
9 6
7 4 98
5 9 72
4 6 10
2 8 22
9 7 17
3 1 66
3
2 8 22
3 1 66
5 6 10
8 6
1 3 84
8 4 34
7 2 10
6 8 8
3 5 39
2 7 8
2
1 5 39
6 4 8
10 8
2 3 49
4 8 26
5 2 76
3 5 94
1 7 16
10 9 77
6 4 24
7 1 7
2
6 8 24
10 9 77
6 5
2 6 47
3 4 27
5 2 47
4 1 62
1 5 61
1
3 6 27
5 4
5 2 9
4 1 94
3 5 82
2 3 58
1
4 1 94
1000 0
0
2 2
1 2 1
2 1 1
0
44 42
4 37 166
34 25 47
28 19 367
20 14 811
8 3 878
39 1 925
35 9 206
32 18 841
16 44 503
5 20 426
22 34 896
44 43 471
17 33 577
40 22 317
24 31 818
37 11 292
21 39 888
6 8 983
43 36 170
11 21 662
36 17 942
18 7 356
2 32 220
12 5 774
19 27 193
13 40 63
15 10 510
30 35 869
41 24 736
42 4 180
23 41 261
9 28 501
29 15 983
10 30 638
7 13 402
26 12 754
25 6 597
27 29 57
1 16 933
31 42 135
33 38 718
14 23 361
2
2 3 47
26 38 135
35 33
22 7 978
5 6 566
20 10 198
6 17 170
7 27 627
24 19 659
31 30 130
34 8 365
23 12 716
4 29 217
8 20 156
26 35 142
3 2 419
15 1 448
17 24 91
18 33 962
30 22 822
9 16 847
2 9 470
10 25 981
16 31 359
19 28 283
28 34 199
11 5 660
25 23 176
29 18 235
12 14 765
14 11 81
27 21 61
21 13 651
35 3 583
1 32 767
13 4 256
2
15 32 448
26 33 61
33 28
12 15 574
11 13 714
13 33 62
9 28 391
22 19 235
6 20 655
23 9 25
8 29 994
21 30 133
17 18 170
32 7 470
14 21 418
7 31 431
3 1 185
1 14 538
33 12 250
31 22 694
2 27 945
16 26 584
19 32 317
27 2 904
15 25 748
29 3 754
24 4 287
18 10 775
30 11 401
10 8 653
28 5 70
5
6 20 655
16 26 584
17 25 62
23 5 25
24 4 287
3 1
1 2 10
1
1 2 10
1 0
0
2 0
0
3 0
0
# ﷽
import sys
import heapq 
from heapq import *
from math import log2,ceil,floor,gcd,sqrt,log,perm,comb,factorial
from random import randrange
from bisect import bisect_left 
from collections import defaultdict, Counter, deque, OrderedDict
from functools import lru_cache, reduce
from bisect import bisect_left, bisect_right
from types import GeneratorType

input = lambda: sys.stdin.buffer.readline().decode().rstrip()



class dict_(dict):
    RANDOM = randrange(2 ** 62)
 
    def __init__(self, dd):
        super().__init__({k ^ self.RANDOM: v for k, v in dd.items()})
 
    def __missing__(self, key):
        return 0
 
    def __setitem__(self, key, value):
        super().__setitem__(key ^ self.RANDOM, value)
 
    def __getitem__(self, item):
        return super().__getitem__(item ^ self.RANDOM)
 
    def __contains__(self, item):
        return super().__contains__(item ^ self.RANDOM)
 
    def items(self):
        for k, v in super().items():
            yield (k ^ self.RANDOM, v)
 
    def keys(self):
        for k in super().keys():
            yield k ^ self.RANDOM
 
    def __repr__(self):
        return '{0}'.format({k ^ self.RANDOM: v for k, v in super().items()})

###############################################################################
# GRAPHS :

def add_edge(node1,node2,graph):

    if node1 not in graph:
        graph[node1] = []
    if node2 not in graph:
        graph[node2] = []
    graph[node1].append(node2)
    graph[node2].append(node1)

class disjointset:
    def __init__(self, n):
        self.rank, self.parent = array('i', [0] * (n + 1)), array('i', [i for i in range(n + 1)])
        self.n, self.even = n, array('b', [0] * (n + 1))
 
    def find(self, x):
        xcopy = x
        while x != self.parent[x]: x = self.parent[x]
        while xcopy != x:
            self.parent[xcopy], xcopy = x, self.parent[xcopy]
        return x
 
    def union(self, x, y):
        xpar, ypar = self.find(x), self.find(y)
 
        if xpar == ypar: return 1
 
        par, child = xpar, ypar
        if self.rank[xpar] < self.rank[ypar]:
            par, child = ypar, xpar
 
        elif self.rank[xpar] == self.rank[ypar]:
            self.rank[xpar] += 1
 
        self.parent[child] = par
        self.even[par] |= self.even[child]
        self.n -= 1
        return 0


def dijkstra(graph, start1):
    distances = {node: float('inf') for node in graph}  # Initialize distances to infinity
    distances[start1] = 0  # Distance from start1 to start1 is 0
    heap = [(0, start1,[start1])]  # Priority queue to store nodes and their distances
    paths = [-1 for i in range(n+1)]
    while heap:
        current_distance, current_node , path = heapq.heappop(heap)  # Get node with smallest distance
        
        if current_distance > distances[current_node]:
            continue  # Skip if distance is already greater than the known distance

        for neighbor, weight in graph[current_node]:
            distance = current_distance + weight  # Calculate tentative distance

            if distance < distances[neighbor]:
                lst = path 
                lst.append(neighbor)
                paths[neighbor] = current_node
                distances[neighbor] = distance  # Update distance if shorter
                heapq.heappush(heap, (distance, neighbor, lst))  # Add neighbor to the heap

    return distances , paths



###############################################################################
def mergeSort(arr, n):
    # A temp_arr is created to store
    # sorted array in merge function
    temp_arr = [0]*n
    return _mergeSort(arr, temp_arr, 0, n-1)
 
# This Function will use MergeSort to count inversions
 
 
def _mergeSort(arr, temp_arr, left, right):
 
    # A variable inv_count is used to store
    # inversion counts in each recursive call
 
    inv_count = 0
 
    # We will make a recursive call if and only if
    # we have more than one elements
 
    if left < right:
 
        # mid is calculated to divide the array into two subarrays
        # Floor division is must in case of python
 
        mid = (left + right)//2
 
        # It will calculate inversion
        # counts in the left subarray
 
        inv_count += _mergeSort(arr, temp_arr,
                                left, mid)
 
        # It will calculate inversion
        # counts in right subarray
 
        inv_count += _mergeSort(arr, temp_arr,
                                mid + 1, right)
 
        # It will merge two subarrays in
        # a sorted subarray
 
        inv_count += merge(arr, temp_arr, left, mid, right)
    return inv_count
 
# This function will merge two subarrays
# in a single sorted subarray
 
 
def merge(arr, temp_arr, left, mid, right):
    i = left     # Starting index of left subarray
    j = mid + 1  # Starting index of right subarray
    k = left     # Starting index of to be sorted subarray
    inv_count = 0
 
    # Conditions are checked to make sure that
    # i and j don't exceed their
    # subarray limits.
 
    while i <= mid and j <= right:
 
        # There will be no inversion if arr[i] <= arr[j]
 
        if arr[i] <= arr[j]:
            temp_arr[k] = arr[i]
            k += 1
            i += 1
        else:
            # Inversion will occur.
            temp_arr[k] = arr[j]
            inv_count += (mid-i + 1)
            k += 1
            j += 1
 
    # Copy the remaining elements of left
    # subarray into temporary array
    while i <= mid:
        temp_arr[k] = arr[i]
        k += 1
        i += 1
 
    # Copy the remaining elements of right
    # subarray into temporary array
    while j <= right:
        temp_arr[k] = arr[j]
        k += 1
        j += 1
 
    # Copy the sorted subarray into Original array
    for loop_var in range(left, right + 1):
        arr[loop_var] = temp_arr[loop_var]
 
    return inv_count
###############################################################################


def Divisors(n) :
    divisors = {}
    for num in [n]: 
        lst = set()
        i = 1
        while i <= sqrt(num):
            
            if (num % i == 0) :
                # If divisors are equal, print only one
                if ( num / i == i) :
                    lst.add(i)
                else :
                    # Otherwise print both
                    lst.update([i,num//i])
                
            i = i + 1
        divisors[num] = list(lst)
    return divisors[num]

def binpow(a, b):
    if b==0:
        return 1
    res = binpow(a,b//2)
    res = pow(res,2,MOD)
    if b%2:
        return (res*a)%MOD
    return res
 
def mod_inverse(a):
    return binpow(a,MOD-2)
 
def factors(n): 
    if n==0:
        return set()   
    return set(reduce(list.__add__, 
                ([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))
 
# factors = [factors(i) for i in range(MAX)]
 
# factorial and inverse factorial
 
# fact = [1]*MAX
# invfact = [1]*MAX
# for i in range(1,MAX):
#     fact[i] = (fact[i-1]*i)%MOD
#     invfact[i] = (invfact[i-1]*mod_inverse(i))%MOD

def inverse_mod(num):
    a = mod-2
    result = 1
    result=pow(num,a,mod)
    return result 

def mex(arr, N):
    # Sort the array
    arr1 = arr.copy()
    arr1.sort()
    mex = 0
    for idx in range(N):
        if arr1[idx] == mex:
            # Increment mex
            mex += 1
    # return mex as answer
    return mex
###############################################################################
    
def mergeDictionary(dict_1, dict_2):
   dict_3 = {**dict_1, **dict_2}
   for key, value in dict_3.items():
       if key in dict_1 and key in dict_2:
               dict_3[key] = value + dict_1[key]
   return dict_3
   
def rindex(lst, value):
    lst.reverse()
    i = lst.index(value)
    lst.reverse()
    return len(lst) - i - 1
    
    
def prefix_sum(arr, length_arr, prefix_sum):
    prefix_sum[0] = arr[0] 

    for i in range(1, length_arr): # 1, 2, 3, 4
        prefix_sum[i] =  prefix_sum[i-1]+ arr[i]
        
def suffix_sum(arr, length_arr, suffix_sum):
    suffix_sum[length_arr-1] = arr[length_arr-1] 

    for i in reversed(range(length_arr-1)): # 3, 2, 1, 0
        suffix_sum[i] = suffix_sum[i+1] + arr[i]

    
letters = [
    'a','b','c','d','e','f',
    'g','h','i','j','k','l',
    'm','n','o','p','q','r',
    's','t','u','v','w','x',
    'y','z']

 
# recursion limit fix decorator, change 'return' to 'yield' and add 'yield' before calling the function
def bootstrap(f):  
    stack = []
    def wrappedfunc(*args, **kwargs):
        if stack:
            return f(*args, **kwargs)
        else:
            to = f(*args, **kwargs)
            while True:
                if type(to) is GeneratorType:
                    stack.append(to)
                    to = next(to)
                else:
                    stack.pop()
                    if not stack:
                        break
                    to = stack[-1].send(to)
            return to
    return wrappedfunc

###############################################################################
###############################################################################
###############################################################################
mod = 10**9 + 7
def dfs(i):
    vis.add(i)
    q = [i]
    mn = float("inf")
    lst = [i]
    while q:
        node = q.pop()
        if node not in graph :
            lst.append(node)
            lst.append(mn)
            return lst
        child , w = graph[node][0]
        mn = min(w,mn)
        if child not in vis :
            vis.add(child)
            q.append(child)
    return []
 
def solve():
    # n = int(input())
    n,m = list(map(int,input().split()))
    global vis,graph
    graph = {}
    for _ in range(m) :
        a,b,w = list(map(int,input().split()))
        try :
            graph[a].append((b,w))
        except :
            graph[a] = [(b,w)]
    vis = set()
    ans = [] 
    for i in graph:
        if i not in vis :
            lst = dfs(i)
            if lst :
                ans.append(lst)
    print(len(ans))
    ans.sort()
    for i in ans:
        print(*i)


###############################################################################
###############################################################################
###############################################################################
 
# for t in range(int(input())):
    # case(t+1)
solve()
