import sys from functools import cmp_to_key input = sys.stdin.buffer.readline # Tarjan version of Edmonds algorithm using Skew heap and DSU class UnionFind: def __init__(self, n): self.parent = [-1] * n self.n = n def root(self, x): if self.parent[x] < 0: return x else: self.parent[x] = self.root(self.parent[x]) return self.parent[x] def merge(self, x, y): x = self.root(x) y = self.root(y) if x == y: return False self.parent[x] += self.parent[y] self.parent[y] = x return True def same(self, x, y): return self.root(x) == self.root(y) class SHNode: def __init__(self, val, src, to): self.l = None self.r = None self.val = val self.add = 0 self.src = src self.to = to def lazy_propagate(self): if self.l is not None: self.l.add += self.add if self.r is not None: self.r.add += self.add self.val += self.add self.add = 0 class SkewHeap: def __init__(self): self.root = None def _meld(self, a, b): if a is None: return b if b is None: return a swap = b.val + b.add < a.val + a.add valEqual = b.val + b.add == a.val + a.add if valEqual: swap = b.src < a.src if swap: a, b = b, a a.lazy_propagate() a.r = self._meld(a.r, b) a.l, a.r = a.r, a.l return a @property def min(self): self.root.lazy_propagate() return self.root.val def push(self, val, src, to): nd = SHNode(val, src, to) self.root = self._meld(self.root, nd) def pop(self): rt = self.root rt.lazy_propagate() self.root = self._meld(rt.l, rt.r) return rt.val def meld(self, other): self.root = self._meld(self.root, other.root) def add(self, val): self.root.add += val def empty(self): return self.root is None def directed_mst(n, edges, root): OFFSET = len(edges) from_ = [0] * n from_cost = [0] * n from_heap = [SkewHeap() for i in range(n)] uf = UnionFind(n) par_e = [-1] * m stem = [-1] * n used = [0] * n used[root] = 2 idxs = [] for idx, (fr, to, cost) in enumerate(edges): from_heap[to].push(cost * OFFSET + idx, fr, to) res = 0 for v in range(n): if used[v] != 0: continue processing = [] chi_e = [] cycle = 0 while used[v] != 2: used[v] = 1 processing.append(v) if from_heap[v].empty(): return -1, [] from_cost[v], idx = divmod(from_heap[v].pop(), OFFSET) from_[v] = uf.root(edges[idx][0]) if stem[v] == -1: stem[v] = idx if from_[v] == v: continue res += from_cost[v] idxs.append(idx) while cycle: par_e[chi_e.pop()] = idx cycle -= 1 chi_e.append(idx) if used[from_[v]] == 1: p = v while True: if not from_heap[p].empty(): from_heap[p].add(-from_cost[p] * OFFSET) if p != v: uf.merge(v, p) from_heap[v].meld(from_heap[p]) p = uf.root(from_[p]) cycle += 1 if p == v: break else: v = from_[v] for v in processing: used[v] = 2 used_e = [False] * m resEdges = [] for idx in reversed(idxs): if used_e[idx]: continue fr, to, cost = edges[idx] resEdges.append((fr, to, cost)) x = stem[to] while x != idx: used_e[x] = True x = par_e[x] return res, resEdges n = int(input()) m = int(input()) edges = [list(map(int, input().split())) for i in range(m)] root = int(input()) def comparer(a, b): res = b[2] - a[2] if res == 0: res = a[0] - b[0] if res == 0: res = a[1] - b[1] return res res, resEdges = directed_mst(n, edges, root) sortedResEdges = list(sorted(resEdges, key=cmp_to_key(comparer))) for e in sortedResEdges: print(f'{e[0]} {e[1]} {e[2]}')