Given is an undirected connected graph with N vertices numbered 1 to N, and M edges numbered 1 to M.
The given graph may contain multi-edges but not self loops.
Each edge has an integer label between 1 and N (inclusive).
Edge i has a label c_i, and it connects Vertex u_i and v_i bidirectionally.
Snuke will write an integer between 1 and N (inclusive) on each vertex (multiple vertices may have the same integer written on them) and then keep only the edges satisfying the condition below, removing the other edges.
Condition: Let x and y be the integers written on the vertices that are the endpoints of the edge. Exactly one of x and y equals the label of the edge.
We call a way of writing integers on the vertices good if (and only if) the graph is still connected after removing the edges not satisfying the condition above. Determine whether a good way of writing integers exists, and present one such way if it exists.

-----Constraints-----
 - 2 \leq N \leq 10^5
 - N-1 \leq M \leq 2 \times 10^5
 - 1 \leq u_i,v_i,c_i \leq N
 - The given graph is connected and has no self-loops.

-----Input-----
Input is given from Standard Input in the following format:
N M
u_1 v_1 c_1
\vdots
u_M v_M c_M

-----Output-----
If there is no good way of writing integers, print No.
Otherwise, print N lines. The i-th line should contain the integer written on Vertex i.
Any good way of writing integers will be accepted.

-----Sample Input-----
3 4
1 2 1
2 3 2
3 1 3
1 3 1

-----Sample Output-----
1
2
1

 - We write 1, 2, and 1 on Vertex 1, 2, and 3, respectively.
 - Edge 1 connects Vertex 1 and 2, and its label is 1.
 - Only the integer written on Vertex 1 equals the label, so this edge will not get removed.
 - Edge 2 connects Vertex 2 and 3, and its label is 2.
 - Only the integer written on Vertex 2 equals the label, so this edge will not be removed.
 - Edge 3 connects Vertex 1 and 3, and its label is 3.
 - Both integers written on the vertices differ from the label, so this edge will be removed.
 - Edge 4 connects Vertex 1 and 3, and its label is 1.
 - Both integers written on the vertices equal the label, so this edge will be removed.
 - After Edge 3 and 4 are removed, the graph will still be connected, so this is a good way of writing integers.

```python

USER_FILENAME = "<user_code>"
import sys, json, builtins
import math, heapq, bisect, itertools, functools, collections, statistics, fractions, decimal, operator, array, random, re, string, os, pathlib
try:
    import resource as _res
except Exception:
    _res = None
from collections import Counter, defaultdict, deque, OrderedDict
from functools import lru_cache, reduce
from itertools import accumulate, permutations, combinations, product
from math import gcd, ceil, floor, sqrt
from decimal import Decimal
try:
    from typing import *
except Exception:
    pass
try:
    sys.setrecursionlimit(1_000_000)
except Exception:
    pass
try:
    import site as _site
    try:
        _sys_sites = _site.getsitepackages() if hasattr(_site, "getsitepackages") else []
        for _p in _sys_sites:
            if _p and _p not in sys.path:
                sys.path.append(_p)
    except Exception:
        pass
    try:
        _usp = _site.getusersitepackages()
        if isinstance(_usp, str):
            _usp = [_usp]
        for _p in _usp:
            if _p and _p not in sys.path:
                sys.path.append(_p)
    except Exception:
        pass
except Exception:
    pass

ns = {"__name__": "__main__"}
for _k, _v in list(globals().items()):
    if not _k.startswith("_"):
        ns[_k] = _v
_CODE = 'import sys\ninput = sys.stdin.readline\n\ndef I(): return int(input())\ndef MI(): return list(map(int, input().split()))\ndef LI(): return list(map(int, input().split()))\nmod=10**9+7\n\n"""\n基本的に達成可能だと思う\n基本は次数が小さいところ(=端)を取れるように頂点の値を決めておけばOk\n問題は同じ頂点に入っている複数の辺が同じ数値の場合.この時は端ではない方にその数値を割り振るか?\n\n長さ4のパスで3辺の値がどれも1のときとか\n\nスターグラフが2つ連結している時とかもめんどいな\n"""\nfrom collections import defaultdict\nclass UnionFind:\n    def __init__(self, N: int):\n        """\n        N:要素数\n        root:各要素の親要素の番号を格納するリスト.\n             ただし, root[x] < 0 ならその頂点が根で-root[x]が木の要素数.\n        rank:ランク\n        """\n        self.N = N\n        self.root = [-1] * N\n        self.rank = [0] * N\n\n    def __repr__(self):\n        return \'\\n\'.join(\'{}: {}\'.format(r, self.members(r)) for r in self.roots())\n\n    def find(self, x: int):\n        """頂点xの根を見つける"""\n        if self.root[x] < 0:\n            return x\n        else:\n            while self.root[x] >= 0:\n                x = self.root[x]\n            return x\n\n    def union(self, x: int, y: int):\n        """x,yが属する木をunion"""\n        # 根を比較する\n        # すでに同じ木に属していた場合は何もしない.\n        # 違う木に属していた場合はrankを見てくっつける方を決める.\n        # rankが同じ時はrankを1増やす\n        x = self.find(x)\n        y = self.find(y)\n        if x == y:\n            return\n        elif self.rank[x] > self.rank[y]:\n            self.root[x] += self.root[y]\n            self.root[y] = x\n        else:\n            self.root[y] += self.root[x]\n            self.root[x] = y\n            if self.rank[x] == self.rank[y]:\n                self.rank[y] += 1\n\n    def same(self, x: int, y: int):\n        """xとyが同じグループに属するかどうか"""\n        return self.find(x) == self.find(y)\n\n    def count(self, x):\n        """頂点xが属する木のサイズを返す"""\n        return - self.root[self.find(x)]\n\n    def members(self, x):\n        """xが属する木の要素を列挙"""\n        _root = self.find(x)\n        return [i for i in range(self.N) if self.find == _root]\n\n    def roots(self):\n        """森の根を列挙"""\n        return [i for i, x in enumerate(self.root) if x < 0]\n\n    def group_count(self):\n        """連結成分の数"""\n        return len(self.roots())\n\n    def all_group_members(self):\n        """{ルート要素: [そのグループに含まれる要素のリスト], ...}のデフォルトディクトを返す"""\n        dd = defaultdict(list)\n        for i in range(N):\n            root=self.find(i)\n            dd[root].append(i)\n        return dd\n    \ndef Kruskal(maxV, edges):\n    edges.sort()\n    newAdj=[[]for _ in range(N)]\n    uf=UnionFind(maxV)\n    ans = 0\n    for e in edges:\n        fro = e[0]\n        to = e[1]\n        if uf.find(fro) != uf.find(to):\n            uf.union(fro,to)\n            ans+=e[0]\n            newAdj[fro].append(to)\n            newAdj[to].append(fro)\n            \n    return newAdj\n\n# ラベルを色と呼ぶ\n\nN,M=MI()\nfrom collections import defaultdict\ndd = defaultdict(int)\nEdge=[]\n\n# 多重辺は無視しても行けそう\n\nfor _ in range(M):\n    u,v,c=MI()\n    u-=1\n    v-=1\n    c-=1\n    if dd[(u,v)]:\n        continue\n    Edge.append((u,v))\n    \n    dd[(u,v)]=c\n    dd[(v,u)]=c\n    \n# 木で十分かな\nadj=Kruskal(N,Edge)\n# print(adj)\n\nCol=[-1]*N\n\nimport queue\nq=queue.Queue()\n\nfor v in adj[0]:\n    q.put((v,0))\n    \n\nwhile not q.empty():\n\n    v,p=q.get()\n    \n    if Col[p]!=dd[(v,p)]:#親を繋げられてないなら\n        Col[v]=dd[(v,p)]\n    else:\n        #親とつなげるためには違う色である必要あり\n        if Col[p]==0:\n            Col[v]=1\n        else:\n            Col[v]=0\n        \n    for nv in adj[v]:\n        if nv==0 or Col[nv]!=-1:\n            continue\n        q.put((nv,v))\n        \n# rootの色を決める，隣接色以外\ncol_0=[0]*N\nfor v in adj[0]:\n    col_0[Col[v]]+=1\n    \nfor i in range(N):\n    if col_0[i]==0:\n        Col[0]=i\n        break\n# print(col_0)\n\nfor i in range(N):\n    print((Col[i]+1))\n\n\n\n'
_co = compile(_CODE, USER_FILENAME, "exec")
exec(_co, ns, ns)

```

Measured memory_bytes: 293808