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.

Difficulty: interview

Starter code:

Solutions:
import sys
sys.setrecursionlimit(10**6)

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

n, m = map(int, input().split())

ans = [-1]*n

uf = UnionFind(n)
g = [[] for i in range(n)]

for i in range(m):
    u, v, c = map(int, input().split())
    if not uf.same(u-1, v-1):
        uf.union(u-1, v-1)
        g[u-1].append((v-1, c))
        g[v-1].append((u-1, c))

def dfs(i):
    for to, c in g[i]:
        if ans[to]==-1:
            if ans[i] == c:
                if c == 1:
                    ans[to] = c+1
                else:
                    ans[to] = c-1
            else:
                ans[to] = c
            dfs(to)

ans = [-1]*n
ans[0] = 1
dfs(0)

if -1 in ans:
    print('No')
    return

ans = [a for a in ans]

print(*ans, sep='\n')


#!/usr/bin python3
# -*- coding: utf-8 -*-

from collections import deque

n, m = list(map(int, input().split()))
edges = [[] for _ in range(n)]
for _ in range(m):
    u, v, c = list(map(int, input().split()))
    edges[u-1].append((v-1, c))
    edges[v-1].append((u-1, c))

ret = [-1] * n
q = deque([0])
ret[0] = 1
while q:
    now = q.popleft()
    for nxt, c in edges[now]:
        if ret[nxt] != -1: continue
        if ret[now] != c:
            ret[nxt] = c
        else:
            ret[nxt] = 2 if c == 1 else 1
        q.append(nxt)
print(('\n'.join(map(str, ret))))


import bisect, collections, copy, heapq, itertools, math, string, sys
input = lambda: sys.stdin.readline().rstrip() 
sys.setrecursionlimit(10**7)
INF = float('inf')
MOD = 10**9+7
def I(): return int(input())
def F(): return float(input())
def SS(): return input()
def LI(): return [int(x) for x in input().split()]
def LI_(): return [int(x)-1 for x in input().split()]
def LF(): return [float(x) for x in input().split()]
def LSS(): return input().split()

def resolve():
    N, M = LI()
    G = collections.defaultdict(list)
    for _ in range(M):
        u, v, c = LI_()
        G[u].append((v, c))
        G[v].append((u, c))
    # print(G)
    ans = [-1] * N
    ans[0] = 1

    # 木に対して必ずよい書き込み方が存在するので、
    # DFSでMSTを辿ってよい書き込み方をすればよい
    def dfs(c, p):
        for n, l in G[c]:
            if ans[n] == -1:
                if ans[c] == l:
                    # 書き込む値がNを越えないようにする
                    if l < N - 1:
                        ans[n] = l + 1
                    else:
                        ans[n] = l - 1
                else:
                    ans[n] = l
                dfs(n, c)

    dfs(0, -1)

    for i in ans:
        print((i + 1))

def __starting_point():
    resolve()

__starting_point()

from collections import deque
def main():
    n,m = map(int,input().split())
    G = dict()
    for i in range(1,n+1):
        G[i] = dict()

    for i in range(m):
        u,v,c = map(int,input().split())
        G[u][v] = c
        G[v][u] = c

    done = [0]*(n+1)
    done[1] = 1

    dq = deque()
    dq.append(1)

    while dq:
        node = dq.popleft()
        for dst,dc in G[node].items():
            if done[dst] == 0:
                if done[node]!=dc:
                    done[dst] = dc
                else:
                    if dc == n:
                        done[dst] = 1
                    else:
                        done[dst] = dc+1
                dq.append(dst)
            

    for i in range(1,n+1):
        print(done[i])
main()

from collections import deque

N, M = list(map(int, input().split()))
uvc = [list(map(int, input().split())) for _ in range(M)]

G = [[] for _ in range(N + 1)]
for i in range(M):
    A = uvc[i][0]
    B = uvc[i][1]
    G[A].append([B, uvc[i][2]])
    G[B].append([A, uvc[i][2]])

seen = [0] * (N + 1)
seen[1] = G[1][0][1]
q = deque([1])
while q:
    t = q.pop()
    for p, e in G[t]:
        if seen[p] > 0:
            continue
        if seen[t] != e:
            seen[p] = e
        else:
            if seen[t] + 1 <= N:
                seen[p] = seen[t] + 1
            elif seen[t] - 1 > 0:
                seen[p] = seen[t] - 1
        q.append(p)

for i in range(1, N + 1):
    if seen[i] == 0:
        print('No')
        return

for i in range(1, N + 1):
    print((seen[i]))


from collections import deque
n,m = [int(i) for i in input().split()]
g = [[] for _ in range(n)]
for _ in range(m):
  u,v,c = [int(i)-1 for i in input().split()]
  g[u].append([v,c])
  g[v].append([u,c])
num = [0]*n
d = deque()
d.append(0)
label = [-1]*n
label[0] = 0
while d:
  a = d.pop()
  if num[a]:
    continue
  num[a] = 1
  for u,c in g[a]:
    if num[u]:
      continue
    if label[a] != c:
      label[u] = c
    elif c == 0:
      label[u] = 1
    else:
      label[u] = 0
    d.appendleft(u)
print("\n".join(map(lambda i : str(i+1), label)))

import sys
input = lambda: sys.stdin.readline().rstrip()
import copy

n,m= map(int, input().split())
a= [list(map(int, input().split())) for i in range(m)]
g = [[] for i in range(n)]

for x,y,z in a:
    g[x-1].append((y-1,z))
    g[y-1].append((x-1,z))


from collections import deque

def tree(s):

    INF=-10**9
    dis = [INF for i in range(n)]
    ans=[0]*n
    dis[s]=0
    ans[s]=1
    def bfs():
        d = deque()
        d.append(s)

        while len(d):
            x = d.popleft()

            for i in range(len(g[x])):
                y=g[x][i][0]
                if dis[y] == INF:
                    d.append(y)
                    dis[y]=dis[x]+1
                    if ans[y]==0:
                        if ans[x] == g[x][i][1]:
                            if ans[x] == n:
                                ans[y] = n - 1
                            else:
                                ans[y]= copy.copy(ans[x])+1
                        else:
                            ans[y] =copy.copy(g[x][i][1])

        return ans
    return bfs()

v=tree(0)
for i in v:
    print(i)

from collections import deque

n,m=map(int,input().split())

N=[0]*n
L=[list() for i in range(n)]
for i in range(m):
  u,v,c=map(int,input().split())
  L[~-u].append([~-v,c])
  L[~-v].append([~-u,c])

N[0],Q=1,deque([0])
while Q:
  u=Q.popleft()
  for v,c in L[u]:
    if N[v]:
      continue
    Q.append(v)
    if N[u]!=c:
      N[v]=c
    else:
      N[v]=1 if c!=1 else 2

print(*N,sep='\n')


# See. https://atcoder.jp/contests/arc108/tasks/arc108_c

import numpy as np

def solve(N, G):
  q = np.zeros(N, dtype=np.uint32)
  q[0] = 1

  labels = np.zeros(N+1, dtype=np.uint32)
  labels[1] = 1
  end = 1

  for head in range(N):
    u = q[head]
    if u < 1 : break
    for v in list(G[u].keys()):
      if labels[v] > 0: continue
      labels[v] = G[u][v] if labels[u] != G[u][v] else labels[u]%N + 1
      q[end] = v
      end += 1
  else:
    return labels[1:]

  return ['No']

def main():
  N, M = [int(x) for x in input().split()]
  G = {}
  for i in range(M):
    u, v, c = [int(x) for x in input().split()]

    for u_, v_ in ((u,v), (v,u)):
      if u_ not in G: G[u_] = {}
      G[u_][v_] = c

  ans = solve(N, G)
  for i in range(len(ans)):
    print((ans[i]))

main()

# vim: ts=2 sw=2


#!/usr/bin/env python3
# from typing import *
# %%
from collections import deque

# def solve(N: int, M: int, u: List[int], v: List[int], c: List[int]) -> List[str]:
def solve(start, adj):
    N = len(adj)
    ans = [0]*N
    ans[start] = 1
    que = deque([start])
    visited = set()
    while que:
        frm = que.popleft()
        visited.add(frm)
        for to, c in adj[frm]:
            if to in visited: continue
            if ans[frm] == c:
                ans[to] = c%N+1
            else:
                ans[to] = c
            que.append(to)
    return ans

# %%
# generated by online-judge-template-generator v4.7.1 (https://github.com/online-judge-tools/template-generator)
def main():
    N, M = list(map(int, input().split()))
    adj = {i:list() for i in range(N)}
    for i in range(M):
        u, v, c = list(map(int, input().split()))
        adj[u-1].append((v-1,c))
        adj[v-1].append((u-1,c))
    ans = solve(0, adj)
    for a in ans:
        print(a)


def __starting_point():
    main()

__starting_point()

import sys
sys.setrecursionlimit(10**6)
f=lambda:map(int,input().split())
n,m=f()
g=[[] for _ in range(n)]
for _ in range(m):
  u,v,l=f()
  g[u-1]+=[(v-1,l)]
  g[v-1]+=[(u-1,l)]
a=[0]*n
def dfs(v,p=-1,l=1):
  a[v]=l
  for c,m in g[v]:
    if c==p or a[c]: continue
    if l==m: m=1+(m==1)
    dfs(c,v,m)
dfs(0)
print(*a,sep='\n')

from sys import setrecursionlimit
setrecursionlimit(10 ** 6)

N, M, *UVC = map(int, open(0).read().split())

E = [[] for _ in range(N + 1)]
for u, v, c in zip(*[iter(UVC)] * 3):
    E[u].append((v, c))
    E[v].append((u, c))

memo = [-1] * (N + 1)
memo[1] = 1

def dfs(cur, par):
    for nxt, c in E[cur]:
        if memo[nxt] != -1 or nxt == par:
            continue
        if memo[cur] == c:
            c = 1 + (c == 1)
        memo[nxt] = c
        dfs(nxt, cur)

dfs(1, 0)

for m in memo[1:]:
    print(m)

import sys
sys.setrecursionlimit(10**6)
n, m = map(int, input().split())
graph = [[] for _ in range(n)]
for _ in range(m):
    u, v, c = map(int, input().split())
    graph[u-1].append((v-1, c))
    graph[v-1].append((u-1, c))

def dfs(node):
    for c_node, label in graph[node]:
        if seen[c_node]:
            continue
        seen[c_node] = True
        if ans[node]==label:
            if label==1:
                ans[c_node] = 2
            else:
                ans[c_node] = 1
        else:
            ans[c_node] = label
        dfs(c_node)

ans = [None]*n
ans[0] = 1
seen = [False]*n
seen[0] = True
dfs(0)
for i in ans:
    print(i)

def main():
    from collections import deque
    import sys
    input = sys.stdin.readline

    n, m = map(int, input().split())

    g = tuple(list() for _ in range(n))
    for _ in range(m):
        u, v, c = (int(x) - 1 for x in input().split())
        g[u].append((v, c))
        g[v].append((u, c))

    def make_tree(r, g):
        ret = tuple(list() for _ in range(n))

        dq = deque()
        dq.append(r)

        vis = [False] * n
        vis[r] = True

        while dq:
            v = dq.popleft()
            for u, c in g[v]:
                if vis[u]:
                    continue
                vis[u] = True
                ret[v].append((u, c))
                dq.append(u)
        return ret

    gt = make_tree(0, g)

    def make_label(r, g):
        ret = [-1] * n
        ret[r] = 0

        dq = deque()
        dq.append(r)

        while dq:
            v = dq.popleft()
            for u, c in g[v]:
                if ret[v] == c:
                    ret[u] = (c + 1) % n
                else:
                    ret[u] = c
                dq.append(u)
        return ret

    label = make_label(0, gt)
    ans = map(lambda e: e + 1, label)
    print(*ans, sep='\n')


def __starting_point():
    main()

__starting_point()

import sys

sys.setrecursionlimit(10 ** 7)
input = sys.stdin.readline
f_inf = float('inf')
mod = 10 ** 9 + 7


class UnionFind:
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        """xの親を返す"""
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        """yをxの根に繋ぐ（マージテク有）"""
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if self.parents[x] > self.parents[y]:
            x, y = y, x
        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def same(self, x, y):
        """xとyが同じ連結成分か判別する"""
        return self.find(x) == self.find(y)

    def size(self, x):
        """xの連結成分の大きさを返す"""
        return -self.parents[self.find(x)]

    def kruskal(self, edge):
        """
        :param edge: edge = [(コスト, 頂点1, 頂点2),...]の形で重み付き隣接リストを渡して下さい
        :return: 最小全域木のコストの和
        """
        edge.sort()
        cost_sum = 0
        for cost, node1, node2 in edge:
            if not self.same(node1, node2):
                cost_sum += cost
                self.union(node1, node2)
        return cost_sum


def resolve():
    def dfs(v):
        for d, u in edge[v]:
            if uf.same(v, u):
                continue
            uf.union(u, v)
            if res[v] != d:
                res[u] = d
            else:
                for i in range(1, n + 1):
                    if i != d:
                        res[u] = i
                        break
            dfs(u)

    n, m = map(int, input().split())
    edge = [[] for _ in range(n)]
    for _ in range(m):
        u, v, c = map(int, input().split())
        edge[u - 1].append([c, v - 1])
        edge[v - 1].append([c, u - 1])

    uf = UnionFind(n)
    res = [0] * n
    res[0] = 1
    dfs(0)
    print(*res, sep="\n")


def __starting_point():
    resolve()

__starting_point()

import sys
input = lambda: sys.stdin.readline().rstrip()

n,m= map(int, input().split())
a= [list(map(int, input().split())) for i in range(m)]
g = [[] for i in range(n)]

for x,y,z in a:
    g[x-1].append((y-1,z))
    g[y-1].append((x-1,z))


from collections import deque

def tree(s):

    ans=[0]*n
    ans[s]=1
    def bfs():
        d = deque()
        d.append(s)

        while len(d):
            x = d.popleft()

            for i in range(len(g[x])):
                y=g[x][i][0]
                if ans[y] == 0:
                    d.append(y)
                    if ans[x] == g[x][i][1]:
                        if ans[x] == n:
                            ans[y] = n - 1
                        else:
                            ans[y] = ans[x] + 1
                    else:
                        ans[y] = g[x][i][1]

        return ans
    return bfs()

v=tree(0)
for i in v:
    print(i)

# https://atcoder.jp/contests/arc108/tasks/arc108_c

from collections import deque

n, m = map(int, input().split())

N = [0] * n
L = [[] for _ in range(n)]
for i in range(m):
  u, v, c = map(int, input().split())
  L[u - 1].append((v - 1, c))
  L[v - 1].append((u - 1, c))

N[0] = 1
Q = deque([0])
while Q:
  u = Q.popleft()
  for v, c in L[u]:
    if N[v]:
      continue
    Q.append(v)
    if N[u] != c:
      N[v] = c
    else:
      if c != 1:
        N[v] = 1 
      else:
        N[v] = 2

print(*N, sep='\n')


import sys
from collections import deque
input=sys.stdin.readline
N, M = list(map(int, input().split()))
c, to = dict(), [[] for _ in range(N)]

def maxmin(x, y):
    if x < y:
        x, y = y, x
    return (x, y)

for i in range(M):
    x,y,z = list(map(int, input().split()))
    x,y = x-1,y-1
    x,y = maxmin(x,y)
    c[(x,y)] = z
    to[x].append(y)
    to[y].append(x)

d = deque()
d.append(0)
seen = [False] * N
seen[0] = True
mark = [1] * N
while len(d) > 0:
    now = d.popleft()
    for next in to[now]:
        if seen[next]:
            continue
        seen[next] = True
        d.append(next)
        xy = maxmin(next, now)
        if mark[now] == c[xy]:
            mark[next] = (mark[now] % N) + 1
        else:
            mark[next] = c[xy]

for i in mark:
    print(i)


from collections import Counter,deque
n,m=map(int,input().split())
lst=[[] for _ in range(n)]
for i in range(m):
    u,v,c=map(int,input().split())
    lst[u-1].append((v-1,c))
    lst[v-1].append((u-1,c))
ans=[1]+[0]*(n-1)
q=deque([0])
while q:
    x=q.pop()
    for i,j in lst[x]:
        if ans[i]!=0:
            continue
        if j==ans[x]:
            if j==n:
                ans[i]=1
            else:
                ans[i]=j+1
        else:
            ans[i]=j
        q.append(i)
print(*ans,sep="\n")

from sys import stdin, setrecursionlimit
import bisect, collections, copy, heapq, itertools, math, string
setrecursionlimit(10**8)

INF = float("inf")
MOD = 1000000007


def input():
    return stdin.readline().strip()

#unionfind
from collections import defaultdict

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        group_members = collections.defaultdict(list)
        for member in range(self.n):
            group_members[self.find(member)].append(member)
        return group_members

    def __str__(self):
        return '\n'.join(f'{r}: {m}' for r, m in self.all_group_members().items())


def main():

    n, m = map(int, input().split())
    uf = UnionFind(n)
    adj = [[] for _ in range(n)]

    for _ in range(m):
        u, v, c = map(int, input().split())
        u -= 1
        v -= 1
        if uf.same(u, v): continue
        adj[u].append((v, c))    
        adj[v].append((u, c))
        uf.union(u, v)

    queue = collections.deque([0])
    ans = [-1]*n
    ans[0] = 1

    while queue:
        now = queue.popleft()
        pnum = ans[now]
        for edge in adj[now]:
            child = edge[0]
            enum = edge[1]
            if ans[child] != -1: continue
            queue.append(child)
            if pnum == enum:
                ans[child] = 1 if pnum != 1 else 2
            else:
                ans[child] = enum
    
    print(*ans, sep="\n")
















    return

def __starting_point():
    main()

__starting_point()

n, m = list(map(int, input().split()))
g = [[] for _ in range(n)]
for _ in range(m):
    u, v, c = list(map(int, input().split()))
    g[u - 1].append((v - 1, c))
    g[v - 1].append((u - 1, c))
s = [0]
d = [1] * n
d[0] = 0
g2 = [[] for _ in range(n)]
while s:
    p = s.pop()
    for node, label in g[p]:
        if d[node]:
            d[node] = 0
            s.append(node)
            g2[p].append((node, label))
            g2[node].append((p, label))
s = [0]
d = [-1] * n
d[0] = 1
while s:
    p = s.pop()
    for node, label in g2[p]:
        if d[node] == -1:
            if d[p] == label:
                if label == n:
                    d[node] = 1
                else:
                    d[node] = label + 1
            else:
                d[node] = label
            s.append(node)
for x in d:
    print(x)


import sys

input = sys.stdin.readline
N, M = map(int, input().split())
uvc = [list(map(int, input().split())) for _ in range(M)]

edge = [[] for i in range(N)]
for u, v, c in uvc:
    u -= 1
    v -= 1
    c -= 1
    edge[u].append((v, c))
    edge[v].append((u, c))
    
label = [-1] * N
label[0] = 0

Q = [0]
while Q:
    v = Q.pop()
    for u, l in edge[v]:
        if label[u] != -1:
            continue
        Q.append(u)
        if label[v] != l:
            label[u] = l
        else:
            label[u] = l + 1

print(*(l + 1 for l in label), sep="\n")

# import sys
# sys.setrecursionlimit(10 ** 6)
# import bisect
from collections import deque


# from decorator import stop_watch
#
#
# @stop_watch
def solve(N, M, uvc):
    tree_map = [[] for _ in range(N + 1)]
    for u, v, c in uvc:
        tree_map[u].append([v, c])
        tree_map[v].append([u, c])
    # [print(t) for t in tree_map]
    ans = [0] * (N + 1)
    visited = [False] * (N + 1)
    visited[1] = True
    ans[1] = 1
    dq = deque([1])
    while dq:
        now = dq.popleft()
        for child, c in tree_map[now]:
            if visited[child]:
                continue
            visited[child] = True
            if c == ans[now]:
                ans[child] = c % N + 1
            else:
                ans[child] = c
            dq.append(child)
    [print(i) for i in ans[1:]]

    # dq = deque([[1, 0, True, 0]])  # now, parent, parent is same label?, label
    # visited[0] = True
    # visited[1] = True
    # while dq:
    #     now, parent, issame, label = dq.popleft()
    #     if not issame:
    #         ans[now] = label
    #     for child, c in tree_map[now]:
    #         if visited[child]:
    #             continue
    #         visited[child] = True
    #         if issame and ans[now] == 0 and c != label:
    #             ans[now] = c
    #         dq.append([child, now, ans[now] == c, c])
    #     if ans[now] == 0:
    #         ans[now] = label % N + 1
    # [print(i) for i in ans[1:]]

    # # check
    # check = [1] * (N + 1)
    # check[0] = 0
    # new_map = [[] for _ in range(N + 1)]
    # for u, v, c in uvc:
    #     if (ans[u] == c) ^ (ans[v] == c):
    #         new_map[u].append(v)
    #         new_map[v].append(u)
    # dq = deque([1])
    # while dq:
    #     now = dq.popleft()
    #     check[now] = 0
    #     for nxt in new_map[now]:
    #         if check[nxt] == 0:
    #             continue
    #         dq.append(nxt)
    # if sum(check) > 0:
    #     print('wrong')


def __starting_point():
    N, M = map(int, input().split())
    uvc = [[int(i) for i in input().split()] for _ in range(M)]
    solve(N, M, uvc)

    # # test
    # from random import randint
    # from func import random_str, random_ints
    #
    # N = 4
    # M = 2 * N
    #
    #
    # def trial():
    #     a, b = 0, 0
    #     while a == b:
    #         a, b = randint(1, N), randint(1, N)
    #     return a, b, randint(1, N)
    #
    # cnt = 0
    # while True:
    #     uvc = [[i, i % N + 1, randint(1, N)] for i in range(1, N + 1)] + \
    #           [trial() for _ in range(randint(0, N))]
    #     solve(N, M, uvc)
    #     cnt += 1
    #     # if cnt % 10 == 0:
    #     #     print(cnt)

__starting_point()

import sys

input = sys.stdin.readline
N, M = list(map(int, input().split()))
uvc = [list(map(int, input().split())) for _ in range(M)]

g = [[] for _ in range(N)]
for u, v, c in uvc:
    u -= 1
    v -= 1
    g[u].append((v, c))
    g[v].append((u, c))

children = [[] for _ in range(N)]
appeared = [False]*N
q = [0]
appeared[0] = True
while q:
    u = q.pop()
    for v, c in g[u]:
        if not appeared[v]:
            children[u].append((v, c))
            q.append(v)
            appeared[v] = True

colors = [None]*N
colors[0] = 1
q = [0]
while q:
    u = q.pop()
    c_u = colors[u]
    for v, c_edge in children[u]:
        colors[v] = c_edge + (c_edge == c_u)
        q.append(v)
print(('\n'.join(map(str, colors))))


import sys
input = sys.stdin.readline
# sys.setrecursionlimit(10**6)

def inp():
    return int(input())
def inps():
    return input().rstrip()
def inpl():
    return list(map(int, input().split()))
def inpls():
    return list(map(str, input().split()))
def _debug(obj):
    print(obj, file=sys.stderr)

# import decimal
# from decimal import Decimal
# decimal.getcontext().prec = 10

# from heapq import heappush, heappop, heapify
# import math
from math import gcd, floor, ceil, factorial
import itertools as it
from collections import deque, defaultdict
from collections import Counter

def lcd(a, b):
    return a * b // gcd(a, b)

def chmin(dp, i, x):
    if x < dp[i]: dp[i] = x; return True
    return False

def chmax(dp, i, x): 
    if x > dp[i]: dp[i] = x; return True
    return False

# ---------------------------------------

N, M = inpl()
graph = [[] for i in range(N)]
for i in range(M):
    u, v, c = inpl()
    graph[u-1].append([v-1, c])
    graph[v-1].append([u-1, c])
ans = [0] * N
ans[0] = 1
q = deque()
q.append(0)
while True:
    if not q:
        break
    i = q.popleft()
    for g in graph[i]:
        j = g[0]
        c = g[1]
        if ans[j] != 0:
            continue
        if ans[i] == c:
            if c + 1 <= N:
                ans[j] = c + 1
            else:
                ans[j] = c - 1
        else:
            ans[j] = c
        q.append(j)
for i in ans:
    print(i)

import sys
input = sys.stdin.readline

def I(): return int(input())
def MI(): return list(map(int, input().split()))
def LI(): return list(map(int, input().split()))
mod=10**9+7

"""
基本的に達成可能だと思う
基本は次数が小さいところ(=端)を取れるように頂点の値を決めておけばOk
問題は同じ頂点に入っている複数の辺が同じ数値の場合.この時は端ではない方にその数値を割り振るか?

長さ4のパスで3辺の値がどれも1のときとか

スターグラフが2つ連結している時とかもめんどいな
"""
from collections import defaultdict
class UnionFind:
    def __init__(self, N: int):
        """
        N:要素数
        root:各要素の親要素の番号を格納するリスト.
             ただし, root[x] < 0 ならその頂点が根で-root[x]が木の要素数.
        rank:ランク
        """
        self.N = N
        self.root = [-1] * N
        self.rank = [0] * N

    def __repr__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

    def find(self, x: int):
        """頂点xの根を見つける"""
        if self.root[x] < 0:
            return x
        else:
            while self.root[x] >= 0:
                x = self.root[x]
            return x

    def union(self, x: int, y: int):
        """x,yが属する木をunion"""
        # 根を比較する
        # すでに同じ木に属していた場合は何もしない.
        # 違う木に属していた場合はrankを見てくっつける方を決める.
        # rankが同じ時はrankを1増やす
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        elif self.rank[x] > self.rank[y]:
            self.root[x] += self.root[y]
            self.root[y] = x
        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            if self.rank[x] == self.rank[y]:
                self.rank[y] += 1

    def same(self, x: int, y: int):
        """xとyが同じグループに属するかどうか"""
        return self.find(x) == self.find(y)

    def count(self, x):
        """頂点xが属する木のサイズを返す"""
        return - self.root[self.find(x)]

    def members(self, x):
        """xが属する木の要素を列挙"""
        _root = self.find(x)
        return [i for i in range(self.N) if self.find == _root]

    def roots(self):
        """森の根を列挙"""
        return [i for i, x in enumerate(self.root) if x < 0]

    def group_count(self):
        """連結成分の数"""
        return len(self.roots())

    def all_group_members(self):
        """{ルート要素: [そのグループに含まれる要素のリスト], ...}のデフォルトディクトを返す"""
        dd = defaultdict(list)
        for i in range(N):
            root=self.find(i)
            dd[root].append(i)
        return dd
    
def Kruskal(maxV, edges):
    edges.sort()
    newAdj=[[]for _ in range(N)]
    uf=UnionFind(maxV)
    ans = 0
    for e in edges:
        fro = e[0]
        to = e[1]
        if uf.find(fro) != uf.find(to):
            uf.union(fro,to)
            ans+=e[0]
            newAdj[fro].append(to)
            newAdj[to].append(fro)
            
    return newAdj

# ラベルを色と呼ぶ

N,M=MI()
from collections import defaultdict
dd = defaultdict(int)
Edge=[]

# 多重辺は無視しても行けそう

for _ in range(M):
    u,v,c=MI()
    u-=1
    v-=1
    c-=1
    if dd[(u,v)]:
        continue
    Edge.append((u,v))
    
    dd[(u,v)]=c
    dd[(v,u)]=c
    
# 木で十分かな
adj=Kruskal(N,Edge)
# print(adj)

Col=[-1]*N

import queue
q=queue.Queue()

for v in adj[0]:
    q.put((v,0))
    

while not q.empty():

    v,p=q.get()
    
    if Col[p]!=dd[(v,p)]:#親を繋げられてないなら
        Col[v]=dd[(v,p)]
    else:
        #親とつなげるためには違う色である必要あり
        if Col[p]==0:
            Col[v]=1
        else:
            Col[v]=0
        
    for nv in adj[v]:
        if nv==0 or Col[nv]!=-1:
            continue
        q.put((nv,v))
        
# rootの色を決める，隣接色以外
col_0=[0]*N
for v in adj[0]:
    col_0[Col[v]]+=1
    
for i in range(N):
    if col_0[i]==0:
        Col[0]=i
        break
# print(col_0)

for i in range(N):
    print((Col[i]+1))





from collections import deque

class Unionfind:
     
    def __init__(self,n):
        self.uf = [-1]*n
 
    def find(self,x):
        if self.uf[x] < 0:
            return x
        else:
            self.uf[x] = self.find(self.uf[x])
            return self.uf[x]
 
    def same(self,x,y):
        return self.find(x) == self.find(y)
 
    def union(self,x,y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return False
        if self.uf[x] > self.uf[y]:
            x,y = y,x
        self.uf[x] += self.uf[y]
        self.uf[y] = x
        return True
 
    def size(self,x):
        x = self.find(x)
        return -self.uf[x]

n,m = map(int,input().split())
e = [[] for i in range(n+1)]
uf = Unionfind(n+1)
for i in range(m):
    u,v,c = map(int,input().split())
    if uf.same(u,v):
        continue
    e[u].append((v,c))
    e[v].append((u,c))

ans = [-1]*(n+1)
ans[1] = 1
q = deque([[1,0]])
while q:
    now,par = q.popleft()
    for nex,col in e[now]:
        if ans[nex] > 0:
            continue
        if ans[now] == col:
            ans[nex] = col%n+1
        else:
            ans[nex] = col
        q.append([nex,now])

for i in ans[1:]:
    print(i)

# https://atcoder.jp/contests/arc108/submissions/18282738
# 前回の提出は間違っている

def main():
    from collections import deque
    import sys
    input = sys.stdin.readline

    n, m = map(int, input().split())

    g = tuple(list() for _ in range(n))
    for _ in range(m):
        u, v, c = (int(x) - 1 for x in input().split())
        c += 1  # 1-based
        g[u].append((v, c))
        g[v].append((u, c))

    def make_label(r):
        ret = [-1] * n  # 1-based
        ret[r] = 1

        vis = [False] * n
        vis[r] = True

        dq = deque()
        dq.append(r)

        while dq:
            v = dq.popleft()
            for u, c in g[v]:
                if vis[u]:
                    continue
                vis[u] = True
                if ret[v] == c:
                    if c == n:  # 前回は0-basedのcとnを比較していた
                        ret[u] = 1
                    else:
                        ret[u] = c + 1
                else:
                    ret[u] = c
                dq.append(u)
        return ret

    lbl = make_label(0)
    print(*lbl, sep='\n')


def __starting_point():
    main()

__starting_point()

#!/usr/bin/env python3
# from typing import *
# %%
from collections import deque

# def solve(N: int, M: int, u: List[int], v: List[int], c: List[int]) -> List[str]:
def solve(start, adj):
    N = len(adj)
    ans = [0]*N
    ans[start] = 1
    que = deque([start])
    while que:
        frm = que.popleft()
        for to, c in adj[frm]:
            if ans[to]: continue
            if ans[frm] == c:
                ans[to] = c+1
            else:
                ans[to] = c
            que.append(to)
    return ans

# %%
# generated by online-judge-template-generator v4.7.1 (https://github.com/online-judge-tools/template-generator)
def main():
    N, M = list(map(int, input().split()))
    adj = {i:list() for i in range(N)}
    for i in range(M):
        u, v, c = list(map(int, input().split()))
        adj[u-1].append((v-1,c))
        adj[v-1].append((u-1,c))
    ans = solve(0, adj)
    for a in ans:
        print(a)


def __starting_point():
    main()

__starting_point()

from collections import deque
N,M=list(map(int,input().split()))
G=[{} for i in range(N)]
for _ in range(M):
    u,v,c=list(map(int,input().split()))
    G[u-1][v-1]=c-1
    G[v-1][u-1]=c-1
ans=[-1 for i in range(N)]
ans[0]=0
q=deque([0])
while(q):
    r=q.pop()
    for p in G[r]:
        if ans[p]!=-1:
            continue
        if ans[r]==G[p][r]:
            ans[p]=(ans[r]+1)%N
        else:
            ans[p]=G[p][r]
        q.append(p)
for i in ans:
    print((i+1))


#C
N,M=map(int,input().split())
P=[-1]*(N+1)
Visited=[False]*(N+1)
Past=[[] for i in range(N+1)]
for i in range(M):
    u,v,c=map(int,input().split())
    Past[u].append((v,c))
    Past[v].append((u,c))
    

from queue import Queue

q=Queue()
q.put(1)
P[1]=1
while not q.empty():
    st=q.get()
    for to,c in Past[st]:
        if P[to]==-1:
            if P[st]==c:
                P[to]=c+1 if c+1<=N else 1
            else:
                P[to]=c
            q.put(to)
            
flag=True
for i in range(1,N+1):
    if P[i]==-1:
        flag=False
        
if flag:
    for i in range(1,N+1):
        print(P[i])
else:
    print("No")

from collections import deque

class Unionfind:
     
    def __init__(self,n):
        self.uf = [-1]*n
 
    def find(self,x):
        if self.uf[x] < 0:
            return x
        else:
            self.uf[x] = self.find(self.uf[x])
            return self.uf[x]
 
    def same(self,x,y):
        return self.find(x) == self.find(y)
 
    def union(self,x,y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return False
        if self.uf[x] > self.uf[y]:
            x,y = y,x
        self.uf[x] += self.uf[y]
        self.uf[y] = x
        return True
 
    def size(self,x):
        x = self.find(x)
        return -self.uf[x]

n,m = map(int,input().split())
e = [[] for i in range(n+1)]
uf = Unionfind(n+1)
for i in range(m):
    u,v,c = map(int,input().split())
    if uf.same(u,v):
        continue
    e[u].append((v,c))
    e[v].append((u,c))

ans = [-1]*(n+1)
ans[1] = 1
q = deque([[1,0]])
while q:
    now,par = q.popleft()
    for nex,col in e[now]:
        if ans[nex] > 0:
            continue
        if ans[now] == col:
            ans[nex] = col%n+1
        else:
            ans[nex] = col
        q.append([nex,now])

for i in ans[1:]:
    print(i)

import sys
input = sys.stdin.readline
from collections import defaultdict, deque
mod = 10 ** 9 + 7; INF = float("inf")

def getlist():
	return list(map(int, input().split()))

class UnionFind(object):
	def __init__(self, N):
		self.par = [i for i in range(N)]
		self.rank = [0] * N

	def find(self, x):
		if self.par[x] == x:
			return x
		else:
			self.par[x] = self.find(self.par[x])
			return self.par[x]

	def same_check(self, x, y):
		return self.find(x) == self.find(y)

	def union(self, x, y):
		x = self.find(x); y = self.find(y)
		if self.rank[x] < self.rank[y]:
			self.par[x] = y
		else:
			self.par[y] = x
			if self.rank[x] == self.rank[y]:
				self.rank[x] += 1

class Graph(object):
	def __init__(self, N):
		self.graph = [[] for i in range(N)]

	def add_edge(self, a, b, c):
		self.graph[a].append((b, c))

def bfs(G, s, N):
	Q = deque(); Q.append(s)
	visit = [0] * N; visit[s] = 1
	label = [None] * N; label[s] = 0
	while Q:
		v = Q.popleft()
		for i, c in G.graph[v]:
			if visit[i] == 0:
				visit[i] = 1
				if c != label[v]:
					label[i] = c
				else:
					if c == N - 1:
						label[i] = 0
					else:
						label[i] = N - 1
				Q.append(i)
	return label

def main():
	N, M = getlist()
	G = Graph(N)
	UF = UnionFind(N)
	for i in range(M):
		u, v, c = getlist()
		u -= 1; v -= 1; c -= 1
		if UF.same_check(u, v) == False:
			UF.union(u, v)
			G.add_edge(u, v, c)
			G.add_edge(v, u, c)

	ans = bfs(G, 0, N)
	for i in ans:
		print(i + 1)


def __starting_point():
	main()
__starting_point()

import sys
from collections import deque


N, M = map(int, input().split())
edge = [[] for _ in range(N)]
for i in range(M):
    u, v, c = map(int, sys.stdin.readline().split())
    u -= 1; v -= 1
    edge[u].append((v, c))
    edge[v].append((u, c))
path = [-1] * N
path[0] = edge[0][0][1]
q = deque()
for v, c in edge[0]:
    q.append((0, v, c))

while q:
    u, v, c = q.popleft()
    if path[v] == -1:
        if path[u] != c:
            vc = c
        else:
            if path[u] > 1:
                vc = path[u] - 1
            else:
                vc = path[u] + 1
        path[v] = vc
        for nv, nc in edge[v]:
            if path[nv] == -1:
                q.append((v, nv, nc))

print(*path, sep='\n')


'''
Hey  why peeping here -_'_- ?
I believe on myself and I will achieve
this->author = Fuad Ashraful Mehmet, CSE ,University of Asia Pacific
Todo:
'''
import sys
input=sys.stdin.readline
from itertools import groupby
from collections import deque

R=lambda:map(int,input().split())
I=lambda:int(input())
S=lambda:input().rstrip('\n')
L=lambda:list(R())

def HalfDead():
    n,m=R()
    g=dict()
    for i in range(1,n+1):
        g[i]=dict()
    
    for i in range(m):
        u,v,c=R()
        g[u][v]=c
        g[v][u]=c
    #print("here")
    color=[0]*(n+2)
    color[1]=1

    dq=deque()
    dq.append(1)

    while dq:
        frm=dq.popleft()

        for to,c in g[frm].items():

            if color[to]==0:
                if color[frm]!=c:
                    color[to]=c
                else:
                    if c==n:
                        color[to]=1
                    else:
                        color[to]=c+1
            
                dq.append(to)
    

    for i in range(n):
        print(color[i+1])
    return

def __starting_point():
    #for _ in range(I()):
    HalfDead()
__starting_point()

from collections import deque

def bfs():
    q = deque()
    q.append(1)
    ans[1] = 1
    while q:
        i = q.popleft()
        for j, c in G[i]:
            if ans[j] == 0:
                if not ans[i] == c:
                    ans[j] = c
                else:
                    ans[j] = 1 if ans[i] >= 2 else 2
                q.append(j)
    return

n, m = map(int, input().split())
G = [[] for _ in range(n + 1)]
for _ in range(m):
    u, v, c = map(int, input().split())
    G[u].append([v, c])
    G[v].append([u, c])
ans = [0] * (n + 1)
bfs()
for i in range(1, n + 1):
    print(ans[i])

from collections import deque
N,M=list(map(int, input().split()))

G=[[] for _ in range(N)]

for i in range(M):
    u,v,c=list(map(int, input().split()))
    G[u-1].append((v-1, c))
    G[v-1].append((u-1, c))

newG=[[] for _ in range(N)]
done=[0]*N
ans=[0]*N

que=deque([0])
ans[0]=1
while que:
    start=que.popleft()
    done[start]=1
    
    for t in G[start]:
        nex, c=t
        if done[nex]==1:
            continue
        else:
            
            newG[start].append((nex, c))
            que.append(nex)
            if ans[start]==c:
                ans[nex]=c%N+1
            else:
                ans[nex]=c

for a in ans:
    print(a)







import sys
input = sys.stdin.readline
from collections import Counter,deque

n,m=map(int,input().split())
E=[list(map(int,input().split())) for i in range(m)]

F=[]

# E = [(cost, v, w), ...]
#   G上の全ての辺(v, w)とそのcostを含むlist

# Union-Findを使うことで頂点間の連結判定を行う

*p, = range(n)
def root(x):
    if x == p[x]:
        return x
    p[x] = y = root(p[x])
    return y

def unite(x, y):
    px = root(x); py = root(y)
    if px == py:
        return 0
    if px < py:
        p[py] = px
    else:
        p[px] = py
    return 1

E.sort()
ans = 0
for  v, w, c in E:
    if unite(v-1, w-1):
        F.append([v,w,c])
        ans += c

# ansが最小全域木の解

g=[[] for i in range(n)]
ans=[0]*n
ans[0]='?'
used=[False]*(n+1)
pre=[0]*n
 
for u,v,c in F:
    g[u-1].append([v-1,c])
    g[v-1].append([u-1,c])

 
 
Q=deque()
Q.append((0))
 
while Q:
    p=Q.popleft()
 
    for s in g[p]:
        i,v=s[0],s[1]
        if ans[i]==0:
            if ans[p]==v:
                ans[i]=v+1
                Q.append((i))
                if ans[i]==n+1:
                    ans[i]=1
            else:
                ans[i]=v
                Q.append((i))
 
 
for i,v in g[0]:
    used[v]=True
 
for i in range(1,n+1):
    if used[i]==False:
        ans[0]=i
        break
 
 
print(*ans,sep='\n')

import sys

sys.setrecursionlimit(10**6)

def dfs(now):
    for nxt, color in edge[now]:
        if res[nxt] == 0:
            if res[now] == color:
                res[nxt] = (color + 1 if color < n else 1)
            else:
                res[nxt] = color
        
            dfs(nxt)
    
    return


n, m = map(int, input().split())
edge = [[] for _ in range(n)]
for _ in range(m):
    u, v, c = map(int, input().split())
    edge[u-1].append([v-1, c])
    edge[v-1].append([u-1, c])

res = [0] * n
res[0] = 1

dfs(0)

print(*res, sep='\n')

from collections import defaultdict
from collections import deque

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        group_members = defaultdict(list)
        for member in range(self.n):
            group_members[self.find(member)].append(member)
        return group_members

    def __str__(self):
        return '\n'.join(f'{r}: {m}' for r, m in list(self.all_group_members().items()))
      
      
      
n,m = list(map(int,input().split()))
V = [[] for i in range(n+1)]

sets = [set([]) for i in range(n+1)]
uf = UnionFind(n+1)
for i in range(m):
    a,b,c = list(map(int,input().split()))
    if uf.find(a) != uf.find(b):
        uf.union(a,b)
        V[a].append([b,c])
        V[b].append([a,c])
        sets[a].add(c)
        sets[b].add(c)
        
p = [-1]*(n+1)

def out_not_in_number(x):
    ret = -1
    for i in range(1,n+1):
        if i not in sets[x]:
            ret = i
            break
    return ret

start = 1
p[start] = out_not_in_number(start)

q = deque([])
q.append(start)
while q:
    x = q.popleft()
    for y,z in V[x]:
        if p[y] == -1:
            q.append(y)
            if p[x] == z:
                p[y] = out_not_in_number(y)
                
            else:
                p[y] = z
for i in range(1,n+1):
    print((p[i]))
#print(V)


from collections import deque

n,m=map(int,input().split())

N=[0]*n
L=[list() for i in range(n)]
for i in range(m):
  u,v,c=map(int,input().split())
  L[~-u].append([~-v,c])
  L[~-v].append([~-u,c])

N[0],Q=1,deque([0])
while Q:
  u=Q.popleft()
  for v,c in L[u]:
    if N[v]:
      continue
    Q.append(v)
    if N[u]!=c:
      N[v]=c
    else:
      N[v]=1 if c!=1 else 2

print(*N,sep='\n')


from collections import deque
n, m = map(int, input().split())
edge = [[] for i in range(n)]
for i in range(m):
    u, v, c = map(int, input().split())
    u-=1; v-=1
    edge[u].append((v, c))
    edge[v].append((u, c))

que = deque([0])
used = [0]*(n+1)
used[0]=1
while que:
    v = que.pop()
    for u, cost in edge[v]:
        if used[u]: continue
        if used[v]==cost:
            used[u] = cost%n+1
        else:
            used[u]=cost
        que.appendleft(u)
for i in range(n):
    print(used[i])

from collections import defaultdict

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        group_members = defaultdict(list)
        for member in range(self.n):
            group_members[self.find(member)].append(member)
        return group_members

    def __str__(self):
        return '\n'.join(f'{r}: {m}' for r, m in list(self.all_group_members().items()))

n, m = list(map(int, input().split()))
un = UnionFind(n)
next_edge_dic = {}
flag = False
for _ in range(m):
    u, v, c = list(map(int, input().split()))
    u -= 1
    v -= 1
    if not un.same(u, v):
        if u not in next_edge_dic:
            next_edge_dic[u] = []
        next_edge_dic[u].append([v, c])
        if v not in next_edge_dic:
            next_edge_dic[v] = []
        next_edge_dic[v].append([u, c])
        un.union(u, v)
    if un.size(0) == n:
        flag = True
        break
if not flag:
    print('No')
else:
    stack = [0]
    visited = set([0])
    ans = [0] * n
    ans[0] = 1
    while stack:
        edge = stack.pop()
        for next_edge, label in next_edge_dic[edge]:
            if next_edge in visited:
                continue
            if ans[edge] == label:
                if label == 1:
                    ans[next_edge] = 2
                else:
                    ans[next_edge] = 1
            else:
                ans[next_edge] = label
            stack.append(next_edge)
        visited.add(edge)
    for i in range(n):
        print((ans[i]))



def main():
    n,m=map(int,input().split())
    G=[-1]*n
    Node = {}
    for i in range(n):
        Node[i+1]=[]
    for i in range(m):
        u,v,c=map(int,input().split())
        Node[u]+=[[v,c]]
        Node[v]+=[[u,c]]
    que = [0]
    G[0]=1
    while len(que)>0:
        q=que.pop(0)
        for nv,w in Node[q+1]:
            if G[nv-1]!=-1:
                continue
            if G[q]==w:
                G[nv-1]=(G[q]+1)%n
            else:
                G[nv-1]=w
            que.append(nv-1)
    cnt=0
    for i in range(n):
        if G[i]==-1:
            cnt+=1
    if cnt>0:
        print('No')
        return
    for i in range(n):
        print(G[i])

def __starting_point():
    main()
__starting_point()

import sys
input=sys.stdin.readline

n,m=map(int,input().split())
G=[[] for _ in range(n+1)]
for _ in range(m):
    u,v,c=map(int,input().split())
    G[u].append((v,c))
    G[v].append((u,c))
q=1
stack=[1]
ans=[0]*(n+1)
ans[1]=1
while stack:
    v=stack.pop()
    for u,c in G[v]:
        if not ans[u]:
            if ans[v]==c: c=c%n+1
            ans[u]=c
            stack.append(u)
            q+=1
            if q==n:
                stack=[]
                break
if q==n: print(*ans[1:],sep='\n')
else: print('No')

import sys
sys.setrecursionlimit(10**9)
N, M = map(int, input().split())
edges = [[] for _ in range(N)]
for _ in range(M):
    u, v, c = map(int, input().split())
    u -= 1
    v -= 1
    edges[u].append((v, c))
    edges[v].append((u, c))

ans = [-1] * N
ans[0] = 1

def dfs(u):
    for v, c in edges[u]:
        if ans[v] != -1: continue
        if ans[u] == c: 
            if c == 1:
                ans[v] = 2
            else:
                ans[v] = 1
        else: 
            ans[v] = c
        dfs(v)

dfs(0)
print(*ans, sep="\n")

import sys
input = lambda: sys.stdin.readline()

n, m = list(map(int, input().split()))
g = [[] for _ in range(n + 1)]

for _ in range(m):
    x, y, c = list(map(int, input().split()))
    g[x].append((y, c))
    g[y].append((x, c))

que = [1]
num = [0] * (n + 1)
num[1] = 1

while que:
    x = que.pop()
    for v, nv in g[x]:
        if num[v]:
            continue
        if num[x] == nv:
            num[v] = nv % n + 1
        else:
            num[v] = nv
        que.append(v)

print(("\n".join(map(str, num[1:]))))


from collections import defaultdict, deque
n, m = map(int, input().split())
G = defaultdict(list)
for _ in range(m):
  i, j, w = map(int, input().split())
  G[i].append((j, w))
  G[j].append((i, w))
ans = [0] * (n + 1)
ans[1] = 1
q = deque([1])
while q:
  node = q.popleft()
  for nei, w in G[node]:
    if ans[nei]: continue
    if ans[node] == w:
      ans[nei] = w + 1 if w < n else 1
    else:
      ans[nei] = w
    q.append(nei)

for i in range(n):
  print(ans[i + 1])

from collections import deque
N, M = list(map(int, input().split()))
c, to = dict(), [[] for _ in range(N)]

def maxmin(x, y):
    if x < y:
        x, y = y, x
    return (x,y)

for i in range(M):
    x,y,z = list(map(int, input().split()))
    x,y = x-1,y-1
    x,y = maxmin(x,y)
    if (x,y) not in c:
        c[(x,y)] = z
        to[x].append(y)
        to[y].append(x)

q = deque([0])
mark = [0] * N
mark[0] = 1
while q:
    now = q.popleft()
    for next in to[now]:
        if mark[next]:
            continue
        cost = c[maxmin(now, next)]
        if mark[now] == cost:
            mark[next] = mark[now] % N + 1
        else:
            mark[next] = cost
        q.append(next)

for i in mark:
    print(i)


N,M = list(map(int,input().split()))
edges=[list([int(x)-1 for x in input().split()]) for _ in range(M)]

adges=[[] for _ in range(N)]
for u,v,c in edges:
    adges[u].append([v,c])
    adges[v].append([u,c])

visited=[False]*N

cur=edges[0][0]
visited[cur]=True


Q=[cur]
use_edges=[]
while Q:
    cur = Q.pop()
    for nex,label in adges[cur]:
        if visited[nex]:
            continue
        else:
            Q.append(nex)
            visited[nex]=True
            use_edges.append([cur,nex,label])


if all(v for v in visited):
    pass
else:
    print("No")
    return

ans=[-1]*N
adj_use=[[] for _ in range(N)]
for u,v,c in use_edges:
    adj_use[u].append([v,c])
    adj_use[v].append([u,c])


cur=None
for i in range(N):
    if len(adj_use[i])==1:
        cur=i
        break

for u,v,l in use_edges:
    if u==cur or v==cur:
        if l==0:
            ans[cur]=1
        else:
            ans[cur]=0
        break
Q=[cur]

while Q:
    cur = Q.pop()
    for nex,label in adj_use[cur]:
        if ans[nex]!=-1:
            continue
        else:
            Q.append(nex)
            if ans[cur]==label:
                ans[nex]=(label+1)%N
            else:
                ans[nex]=label

for a in ans:
    print((a+1))


import sys
from collections import deque
sys.setrecursionlimit(10**7)
def I(): return int(sys.stdin.readline().rstrip())
def MI(): return map(int,sys.stdin.readline().rstrip().split())
def LI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def LI2(): return list(map(int,sys.stdin.readline().rstrip()))
def S(): return sys.stdin.readline().rstrip()
def LS(): return list(sys.stdin.readline().rstrip().split())
def LS2(): return list(sys.stdin.readline().rstrip())


class UnionFind:
    def __init__(self,n):
        self.par = [i for i in range(n+1)]  # 親のノード番号
        self.rank = [0]*(n+1)

    def find(self,x):  # xの根のノード番号
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]

    def same_check(self,x,y):  # x,yが同じグループか否か
        return self.find(x) == self.find(y)

    def unite(self,x,y):  # x,yの属するグループの併合
        x = self.find(x)
        y = self.find(y)
        if self.rank[x] < self.rank[y]:
            x,y = y,x
        if self.rank[x] == self.rank[y]:
            self.rank[x] += 1
        self.par[y] = x


N,M = MI()
Graph = [[] for _ in range(N+1)]
UF = UnionFind(N)

for _ in range(M):
    u,v,c = MI()
    if not UF.same_check(u,v):
        UF.unite(u,v)
        Graph[u].append((v,c))
        Graph[v].append((u,c))

deq = deque([1])
ANS = [-1]*(N+1)
ANS[1] = 1
while deq:
    i = deq.pop()
    for j,c in Graph[i]:
        if ANS[j] != -1:
            continue
        if ANS[i] != c:
            ANS[j] = c
        else:
            if c == 1:
                ANS[j] = 2
            else:
                ANS[j] = 1
        deq.append(j)

print(*ANS[1:],sep='\n')


from collections import deque

N, M = list(map(int, input().split()))
Edge = [[] for _ in range(N)]
for _ in range(M):
    u, v, c = list(map(int, input().split()))
    u -= 1
    v -= 1
    Edge[u].append((v, c))
    Edge[v].append((u, c))

Ans = [-1] * N
Ans[0] = 1
Q = deque()
Q.append(0)

while Q:
    now = Q.popleft()
    for nex, color in Edge[now]:
        if Ans[nex] != -1:
            continue
        if color == Ans[now]:
            Ans[nex] = color + 1
            Q.append(nex)
        else:
            Ans[nex] = color
            Q.append(nex)
if -1 in Ans:
    print('No')
else:
    for ans in Ans:
        print(ans)


import sys
sys.setrecursionlimit(10**8)

class union_find:
  def __init__(self, n):
    self.par = [-1] * n

  def find(self, x):#xの親を見つける
    if self.par[x] < 0:
      return x
    else:
      self.par[x] = self.find(self.par[x])
      return self.par[x]

  def unite(self,x,y):#要素xとｙを併合させる
    x,y=self.find(x),self.find(y)#xとyの親の検索
    if x!=y:#親が異なる場合併合させる
      if x>y:
        x,y=y,x#小さい方をxとする. これにより要素の値が小さいものを優先して木の根とする. 
      self.par[x]+=self.par[y] #値を無向木の要素数の和にする.
      self.par[y]=x #枝側は根の位置を格納

  def same(self, x, y):#要素xと要素yが同じ無向木に所属しているかを判定する
    return self.find(x) == self.find(y)#同じ値を持つか否か

  def size(self, x):#要素xが所属する無向木の大きさを返す
    return-self.par[self.find(x)]
  
n, m = map(int, input().split())
gragh = [[] for _ in range(n)]
ans = [-1]*n
def dfs(now):
  for nex, c in gragh[now]:
    if ans[nex] != -1:continue
    if ans[now] == c:
      ans[nex] = (c+1)%n + 1
    else:
      ans[nex] = c
    dfs(nex)
    
def main():
  tree = union_find(n)
  for i in range(m):
    u, v, c = map(int, input().split())
    if not tree.same(u-1, v-1):
      tree.unite(u-1, v-1)
      gragh[u-1].append([v-1, c])
      gragh[v-1].append([u-1, c])
  ans[0] = 1
  dfs(0)
  for i in ans:
    print(i)
    
def __starting_point():
  main()
__starting_point()

N, M = map(int, input().split())
UVC = [[int(x)for x in input().split()] for _ in range(M)]

tree = [[] for _ in range(N)]
for u, v, c in UVC:
    u -= 1
    v -= 1
    tree[u].append((v, c))
    tree[v].append((u, c))

result = [0] * N
result[0] = 1  # 適当
stack = [0]
while stack:
    current = stack.pop()
    for child, label in tree[current]:
        if result[child] != 0:
            continue
        stack.append(child)
        if result[current] == label:
            result[child] = label + 1 if label < N else 1
        else:
            result[child] = label

print(*result, sep='\n')


class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

n, m = map(int, input().split())

g = [[] for _ in range(n)]
uf = UnionFind(n)
for _ in range(m):
    u, v, c = map(lambda x: int(x) - 1, input().split())
    if uf.find(u) != uf.find(v):
        g[u].append([v, c])
        g[v].append([u, c])
        uf.union(u, v)
#print(g)


node_val = [None] * n
node_val[0] = 0
que = [0]
seen = set()
#BFS
while que != []:
    temp = []
    for node in que:
        if node in seen:
            continue
        for next_node, c in g[node]:
            if next_node in seen:
                continue
            if node_val[node] == c:
                node_val[next_node] = (c+1) % n
            else:
                node_val[next_node] = c

            #update
            temp.append(next_node)

        seen.add(node)

    que = temp

for val in node_val:
    print(val + 1)

# https://atcoder.jp/contests/arc108/submissions/18282738

def main():
    from collections import deque
    import sys
    input = sys.stdin.readline

    n, m = map(int, input().split())

    g = tuple(list() for _ in range(n))
    for _ in range(m):
        u, v, c = (int(x) - 1 for x in input().split())
        g[u].append((v, c))
        g[v].append((u, c))

    def make_label(r):
        ret = [-1] * n
        ret[r] = 0

        vis = [False] * n
        vis[r] = True

        dq = deque()
        dq.append(r)

        while dq:
            v = dq.popleft()
            for u, c in g[v]:
                if vis[u]:
                    continue
                vis[u] = True
                if ret[v] == c:
                    if c == n:
                        ret[u] = 0
                    else:
                        ret[u] = c + 1
                else:
                    ret[u] = c
                dq.append(u)
        return ret

    label = make_label(0)
    ans = map(lambda e: e + 1, label)
    print(*ans, sep='\n')


def __starting_point():
    main()

__starting_point()

from sys import stdin
import sys

sys.setrecursionlimit(10**6)

N, M = list(map(int, stdin.readline().split()))

g = [[] for i in range(0, N)]

for i in range(0, M):
    a, b, c = list(map(int, stdin.readline().split()))
    a -= 1
    b -= 1
    g[a].append((b, c))
    g[b].append((a, c))

vis = [False] * N
col = [-1] * N


def dfs(v):
    nonlocal vis
    nonlocal col
    vis[v] = True

    for to, c in g[v]:
        if vis[to] == True:
            continue
        if c == col[v]:
            if c == 1:
                col[to] = 2
            else:
                col[to] = 1
        else:
            col[to] = c

        dfs(to)


col[0] = 1
dfs(0)

for i in range(0, N):
    print((col[i]))


import collections as co

n,m = list(map(int,input().split()))

ansDic = dict()
edgeLis = [[] for i in range(n+1)]
for i in range(1,n+1):
    ansDic[i] = 0
for i in range(1,m+1):
    edge = list(map(int,input().split()))
    edgeLis[edge[0]].append([edge[1],edge[2]])
    edgeLis[edge[1]].append([edge[0],edge[2]])

q = co.deque()
q.append(1)
while len(q) > 0:
    k = q.popleft()
    if ansDic[k] == 0:
        ansDic[k] = k
    for lis in edgeLis[k]:
        l1 = lis[0]
        l2 = lis[1]
        if ansDic[l1] == 0:
            q.append(l1)
            if ansDic[k] != l2:
                ansDic[l1] = l2
            elif l1 != l2:
                ansDic[l1] = l1
            else:
                ansDic[l1] = k

#print(ansDic)
for i in range(1,n+1):
    print(ansDic[i])

import sys
sys.setrecursionlimit(10**6)
readline = sys.stdin.readline

class UnionFind:
    def __init__(self, n):
        self.table = [-1] * n
 
    def _root(self, x):
        stack = []
        tbl = self.table
        while tbl[x] >= 0:
            stack.append(x)
            x = tbl[x]
        for y in stack:
            tbl[y] = x
        return x
 
    def find(self, x, y):
        return self._root(x) == self._root(y)
 
    def union(self, x, y):
        r1 = self._root(x)
        r2 = self._root(y)
        if r1 == r2:
            return
        d1 = self.table[r1]
        d2 = self.table[r2]
        if d1 <= d2:
            self.table[r2] = r1
            if d1 == d2:
                self.table[r1] -= 1
        else:
            self.table[r1] = r2

def main():
    N, M = map(int, readline().split())
    all_edges = [tuple(map(int, readline().split())) for _ in range(M)]

    G = [[] for _ in range(N + 1)]
    edges = []
    edge_to_label = {}
    U = UnionFind(N + 1)
    while all_edges:
        u, v, c = all_edges.pop()
        if U.find(u, v):
            continue
        U.union(u, v)
        G[u].append(v)
        G[v].append(u)
        edges.append((u, v))
        edge_to_label[(u, v)] = c
        edge_to_label[(v, u)] = c

    label = [0]*(N + 1)
    label[1] = 1
    stack = [1]
    while stack:
        x = stack.pop()
        for y in G[x]:
            if label[y] > 0:
                continue
            l = edge_to_label[(x, y)]
            if label[x] == l:
                label[y] = (l + 1) % N + 1
                stack.append(y)
            else:
                label[y] = l
                stack.append(y)

    print(*label[1:], sep='\n')

def __starting_point():
    main()


__starting_point()

from collections import deque
n,m = [int(i) for i in input().split()]
g = [[] for _ in range(n)]
for _ in range(m):
  u,v,c = [int(i)-1 for i in input().split()]
  g[u].append([v,c])
  g[v].append([u,c])
num = [0]*n
d = deque()
d.append(0)
label = [-1]*n
label[0] = 0
while d:
  a = d.pop()
  if num[a]:
    continue
  num[a] = 1
  for u,c in g[a]:
    if num[u]:
      continue
    if label[a] != c:
      label[u] = c
    elif c == 0:
      label[u] = 1
    else:
      label[u] = 0
    d.appendleft(u)
for i in range(n):
  label[i] = str(label[i]+1)
print("\n".join(label))

import sys
input = sys.stdin.readline
N,M = map(int,input().split())
UVC = [tuple(map(int,input().split())) for i in range(M)]

es = [[] for _ in range(N)]
for u,v,c in UVC:
    u,v = u-1,v-1
    es[u].append((v,c))
    es[v].append((u,c))

ans = [-1] * N
ans[0] = 1
stack = [0]
visited = [0] * N
visited[0] = 1
while stack:
    v = stack.pop()
    for to,c in es[v]:
        if visited[to]: continue
        visited[to] = 1
        if ans[v] == c:
            ans[to] = c+1 if c+1 <= N else 1
        else:
            ans[to] = c
        stack.append(to)

print(*ans, sep='\n')

from collections import deque

n,m=map(int,input().split())

N=[0]*n
L=[list() for i in range(n)]
for i in range(m):
  u,v,c=map(int,input().split())
  L[~-u].append([~-v,c])
  L[~-v].append([~-u,c])

N[0],Q=1,deque([0])
while Q:
  u=Q.popleft()
  for v,c in L[u]:
    if N[v]:
      continue
    Q.append(v)
    if N[u]!=c:
      N[v]=c
      continue
    for i in range(1,n+1):
      if i!=c:
        N[v]=i
        break

print(*N,sep='\n')


import collections
N, M, *UVC = [int(_) for _ in open(0).read().split()]
U, V, C = [UVC[_::len('UVC')] for _ in range(len('UVC'))]
CUV = []
for u, v, c in zip(U, V, C):
    CUV += [(c, u, v)]
CUV.sort()


class UnionFind():
    def __init__(self, n):
        self.n = n
        self.root = [-1] * (n + 1)
        self.rank = [0] * (n + 1)

    def find(self, x):
        if self.root[x] < 0:
            return x
        else:
            self.root[x] = self.find(self.root[x])
            return self.root[x]

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return 0
        elif self.rank[x] > self.rank[y]:
            self.root[x] += self.root[y]
            self.root[y] = x
        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            if self.rank[x] == self.rank[y]:
                self.rank[y] += 1

    def is_same(self, x, y):
        return self.find(x) == self.find(y)

    def size(self, x):
        return -self.root[self.find(x)]


uf = UnionFind(N)
G = [{} for _ in range(N + 1)]
se = set()
for c, u, v in CUV:
    if uf.is_same(u, v):
        continue
    uf.unite(u, v)
    se.add(c)
    G[u][v] = G[v][u] = c
other = (set(range(1, N + 1)) - se).pop()
ans = [-1] * (N + 1)
ans[1] = 1
uf2 = UnionFind(N)
S = [1]
while S:
    u = S.pop()
    for v in G[u]:
        if uf2.is_same(u, v):
            continue
        uf2.unite(u, v)
        c = G[u][v]
        ans[v] = c if c != ans[u] else c % N + 1
        S += [v]
print(*ans[1:], sep='\n')


#!/usr/bin/env python3
# from typing import *
# %%
from collections import deque

# def solve(N: int, M: int, u: List[int], v: List[int], c: List[int]) -> List[str]:
def solve(start, adj):
    N = len(adj)
    ans = [0]*N
    ans[start] = 1
    que = deque([start])
    while que:
        frm = que.popleft()
        for to, c in adj[frm]:
            if ans[to]: continue
            if ans[frm] == c:
                ans[to] = c%N+1
            else:
                ans[to] = c
            que.append(to)
    return ans

# %%
# generated by online-judge-template-generator v4.7.1 (https://github.com/online-judge-tools/template-generator)
def main():
    N, M = list(map(int, input().split()))
    adj = {i:list() for i in range(N)}
    for i in range(M):
        u, v, c = list(map(int, input().split()))
        adj[u-1].append((v-1,c))
        adj[v-1].append((u-1,c))
    ans = solve(0, adj)
    for a in ans:
        print(a)


def __starting_point():
    main()

__starting_point()

from collections import defaultdict, deque
n, m = map(int, input().split())
G = defaultdict(list)
for _ in range(m):
  i, j, w = map(int, input().split())
  G[i].append((j, w))
  G[j].append((i, w))
ans = [0] * (n + 1)
ans[1] = 1
q = deque([1])
while q:
  node = q.popleft()
  for nei, w in G[node]:
    if ans[nei]: continue
    if ans[node] == w:
      ans[nei] = w + 1 if w < n else 1
    else:
      ans[nei] = w
    q.append(nei)
for i in range(n):
  print(ans[i + 1])

import sys

input = sys.stdin.readline

def main():
    N, M = map(int, input().split())
    number = [0] * N
    edges = [[] for _ in range(N)]
    for _ in range(M):
        u, v, c = map(int, input().split())
        u -= 1; v -= 1
        edges[u].append((v, c))
        edges[v].append((u, c))

    # import
    from collections import deque
    
    # BFS for tree
    # please prefer those objects
    # ki: adjacency list
    # N: length of vertex list
    fr = 0
    que = deque([fr])
    number[fr] = 1
    for _ in range(N**2):
        fr = que.popleft()
        for to, c in edges[fr]:
            if number[to] == 0:
                que.append(to)
                if number[fr] != c:
                    number[to] = c
                else:
                    if c == 1:
                        number[to] = 2
                    else:
                        number[to] = 1
        if len(que) == 0:
            break

    print(*number, sep = '\n')

def __starting_point():
    main()

__starting_point()

N, M = map(int, input().split())

E = [[] for _ in range(N)]
for _ in range(M):
  u, v, c = map(int, input().split())
  u -= 1
  v -= 1
  E[u].append((c, v))
  E[v].append((c, u))

from heapq import heappush, heappop, heapify
used = [0]*N
que = [(c, next, 0) for c, next in E[0]]
used[0] = 1
heapify(que)

ans = [-1]*N
ans[0] = 1

while que:
  cv, v, pre = heappop(que)
  if used[v]:
    continue
  used[v] = 1
  if cv == ans[pre]:
    ans[v] = N - (-(cv + 1)%N)
  else:
    ans[v] = cv
  for cost, next in E[v]:
    if used[next]:
      continue
    heappush(que, (cost, next, v))

print("\n".join([str(i) for i in ans]))

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x): #親を返す
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def unite(self, x, y): #和集合の生成
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x): #所属する集合の大きさ
        return -self.parents[self.find(x)]

    def same(self, x, y): #同じ集合に属しているか判定
        return self.find(x) == self.find(y)

    def members(self, x): #同じ集合に属する要素全列挙
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self): #集合のリーダー全列挙
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self): #集合の数
        return len(self.roots())

    def all_group_members(self): #辞書型,{(リーダーの番号):(その集合の要素全列挙)}
        self.group={r:[] for r in self.roots()}
        for i in range(self.n):
            self.group[self.find(i)].append(i)
        return self.group

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

from collections import deque
import sys
input=sys.stdin.readline

n, m = map(int, input().split())
uf = UnionFind(n)
e = [[] for _ in range(n)]
for i in range(m):
    u, v, c = map(int, input().split())
    u -= 1
    v -= 1
    if uf.same(u, v):
        continue
    e[u].append((v, c))
    e[v].append((u, c))

que = deque()
que.append(0)
ans = [-1] * n
ans[0] = 1

while que:
    now = que.popleft()
    for i, j in e[now]:
        if ans[i] != -1:
            continue
        if ans[now] == j:
            ans[i] = (j+1)%n
            if ans[i] == 0:
                ans[i] = n
        else:
            ans[i] = j
        que.append(i)

print(*ans, sep = "\n")

from collections import defaultdict, deque

n, m = map(int, input().split())
G = defaultdict(list)

for _ in range(m):
    i, j, w = map(int, input().split())
    G[i].append((j, w))
    G[j].append((i, w))

ans = [0] * (n + 1)
ans[1] = 1
q = deque([1])

while q:
    node = q.popleft()
    for nei, w in G[node]:
        if ans[nei]: 
            continue
        # 現在のノードに書き込まれた数と、辺の数字が一致
        if ans[node] == w:
            # 異なる数字を次のノードに入れる
            ans[nei] = w + 1 if w < n else 1
        # 現在のノードに書き込まれた数と、辺の数字が不一致
        else:
            ans[nei] = w
        q.append(nei)

for i in range(n):
    print(ans[i + 1])

import sys
from collections import deque
from heapq import heappush, heappop
def input(): return sys.stdin.readline().strip()

def main():
    N, M = list(map(int, input().split()))
    repn = [[] for _ in range(N + 1)]
    for _ in range(M):
        u, v, c = list(map(int, input().split()))
        repn[u].append((c, v))
        repn[v].append((c, u))
    """
    グラフにおける構築問題、spanning treeを考えるとうまくいくのは王道なのか？
    最小全域木はプリムでいいのかな、随分久しぶりに使う。

    木が作れたら、根から順番にラベル付を行う。
    例えばある親ノードpから辺ラベルcのついた辺で降りてきた頂点vを考えるとき、
    頂点vにはラベルcをつける。そして子に順々と下っていく。
    最初の根につけるラベルは、根から伸びるどの辺のラベルとも一致しないラベルを付ければ良い。
    これは木の辺が頂点数より１小さいことから必ずできることが保証される！

    注意点として、親の親から連続で辺のラベルが連続で一致する場合、この作戦だと
    親と子で頂点のラベルが一致するので辺が切れてしまう。
    なのでこの場合だけ子には親と違うラベルをランダムに当てる。
    """
    # Prim
    visited = [0] * (N + 1)
    used_edge = [[] for _ in range(N + 1)]
    edge_q = []
    for c, v in repn[1]:
        heappush(edge_q, (c, 1, v))
    visited[1] = 1

    while edge_q:
        c, u, v = heappop(edge_q)
        if visited[v]: continue
        visited[v] = 1
        used_edge[u].append((c, v))
        for nc, nv in repn[v]:
            if not visited[nv]: heappush(edge_q, (nc, v, nv))
        
    # Labeling
    label = [0] * (N + 1)
    cand = set(range(1, N + 1))
    for c, v in used_edge[1]: cand.discard(c)
    label[1] = cand.pop()

    q = deque()
    for c, v in used_edge[1]: q.append((c, 1, v))
    while q:
        c, u, v = q.popleft()
        if label[u] == c:
            label[v] = 1 if c != 1 else 2
        else:
            label[v] = c
        for nc, nv in used_edge[v]:
            q.append((nc, v, nv))

    for i, l in enumerate(label):
        if i == 0: continue
        print(l)

def __starting_point():
    main()





__starting_point()

import sys
sys.setrecursionlimit(10**9)
read = lambda:sys.stdin.readline()

def read_ints():
    return list(map(int,read().split()))
def read_intgrid(h):
    return list(list(map(int,read().split()))for i in range(h))
def read_strgrid(h):
    return list(list(read())for i in range(h))

def main():
    #input data
    n,m = map(int,input().split())
    G = [[] for _ in range(n)]
    for i in range(m):
        a,b,c = map(int,input().split())
        a,b = a-1,b-1
        G[a].append((b,c))
        G[b].append((a,c))

    #solve
    #dfsで全域木を走査していく。親ノードと辺のラベルが同じならそれ以外のものを、異なるならラベルを頂点に振っていく

    vis = [0]*n
    label = [-1]*n
    label[0]=1

    def dfs(v):
        vis[v]=1
        for x,c in G[v]:
            if vis[x]:continue
            # print(x,c,label)
            if label[x]==-1:
                if label[v]==c:
                    if label[v]==1:
                        label[x]=label[v]+1
                    else:
                        label[x]=label[v]-1
                else:
                    label[x]=c
            dfs(x)
    dfs(0)
    print('\n'.join(map(str,label))) 
    return None
def __starting_point():
    main()
__starting_point()

#BFS_領域木_無向グラフ_多重辺
#空のリストの集合は[[] for i in range(n)]を用いる。後者だとすべてリンクしてしまう。
from collections import deque
n, m = map(int, input().split())
edge = [[] for i in range(n)]
for i in range(m):
    u, v, c = map(int, input().split())
    u-=1; v-=1
    edge[u].append((v, c))
    edge[v].append((u, c))

que = deque([0])
used = [0]*(n+1)
used[0]=1
while que:
    v = que.pop()
    for u, cost in edge[v]:
        if used[u]: continue
        if used[v]==cost:
            used[u] = cost%n+1
        else:
            used[u]=cost
        que.appendleft(u)
for i in range(n):
    print(used[i])

import sys
from collections import deque
input=sys.stdin.readline
N, M = list(map(int, input().split()))
c, to = dict(), [[] for _ in range(N)]

def maxmin(x, y):
    if x < y:
        x, y = y, x
    return (x,y)

for i in range(M):
    x,y,z = list(map(int, input().split()))
    x,y = x-1,y-1
    x,y = maxmin(x,y)
    if (x,y) not in c:
        c[(x,y)] = z
        to[x].append(y)
        to[y].append(x)

q = deque([0])
mark = [0] * N
mark[0] = 1
while q:
    now = q.popleft()
    for next in to[now]:
        if mark[next]:
            continue
        cost = c[maxmin(now, next)]
        if mark[now] == cost:
            mark[next] = mark[now] % N + 1
        else:
            mark[next] = cost
        q.append(next)

for i in mark:
    print(i)