package main
import (
"bufio"
"os"
"strconv"
)
var scanner *bufio.Scanner
var writer *bufio.Writer
func init() {
scanner = bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanWords)
writer = bufio.NewWriter(os.Stdout)
}
func nextInt() int {
scanner.Scan()
val, _ := strconv.Atoi(scanner.Text())
return val
}
func main() {
defer writer.Flush()
if !scanner.Scan() {
return
}
n, _ := strconv.Atoi(scanner.Text())
q := nextInt()
upper := make([]int, n+1)
mask := (1 << 30) - 1
for i := range upper {
upper[i] = mask
}
type Constraint struct {
u, v, x int
}
constraints := make([]Constraint, q)
for k := 0; k < q; k++ {
u := nextInt()
v := nextInt()
x := nextInt()
constraints[k] = Constraint{u, v, x}
upper[u] &= x
upper[v] &= x
}
lower := make([]int, n+1)
type Edge struct {
to, x int
}
adj := make([][]Edge, n+1)
for _, c := range constraints {
u, v, x := c.u, c.v, c.x
if u == v {
lower[u] |= x
} else {
lower[u] |= (x &^ upper[v])
lower[v] |= (x &^ upper[u])
if u < v {
adj[u] = append(adj[u], Edge{v, x})
} else {
adj[v] = append(adj[v], Edge{u, x})
}
}
}
a := make([]int, n+1)
for i := 1; i <= n; i++ {
val := lower[i]
a[i] = val
for _, e := range adj[i] {
req := e.x &^ val
lower[e.to] |= req
}
}
for i := 1; i <= n; i++ {
if i > 1 {
writer.WriteByte(' ')
}
writer.WriteString(strconv.Itoa(a[i]))
}
writer.WriteByte('\n')
}