#include <cstdio>
struct t_Edge {
	int next;
	int to;
	int c;
};
t_Edge edge[400010];
int N, M, a, b, w;
int father[200010];
int head[200010], num_edge;
int vis[200010], ans[200010];
void add(int from, int to, int c)
{
	edge[++num_edge].next = head[from];
	edge[num_edge].to = to;
	edge[num_edge].c = c;
	head[from] = num_edge;
}
int find(int x)
{
	if(father[x]!=x)
	    father[x] = find(father[x]);
	return father[x];
}
void DFS(int u)
{
	for(int i=head[u];i;i=edge[i].next)
	{
		int v = edge[i].to;
		if(vis[v])
		    continue;
		vis[v] = 1;
		if(ans[u]==edge[i].c)
		{
			if(edge[i].c==1)
			    ans[v] = 2;
			else
			    ans[v] = 1;
		}
		else ans[v] = edge[i].c;
		DFS(v);
	}
}
int main()
{
	scanf("%d%d", &N, &M);
	for(int i=1;i<=N;i++)
	    father[i] = i;
	for(int i=1;i<=M;i++)
	{
		scanf("%d%d%d", &a, &b, &w);
		int r1 = find(a), r2 = find(b);
		if(r1==r2)
		    continue;
		father[r2] = r1;
		add(a, b, w);
		add(b, a, w);
	}
	vis[1] = ans[1] = 1;
	DFS(1);
	for(int i=1;i<=N;i++)
	    printf("%d\n", ans[i]);
	return 0;
}
#include <bits/stdc++.h>
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#define ll long long
#define ALL(a) (a).begin(),(a).end()
#define rep(i,n) for(int i=0;i<(n);i++)
#define rrep(i,n) for(int i=n-1;i>=0;i--)
#define Pii pair<int,int>
#define Pll pair<long long,long long>
#define fout(num) cout << fixed << setprecision(20) << (num) << endl
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
//vector<vector<ll>> dp(n,vector<ll>(n))
//2-dim:vector<vector<Type>> vv(n, vector<Type>(m, d));
//3-dim:vector<vector<vector<Type>>> vvv(n, vector<vector<Type>>(m, vector<Type>(l, d)));

using namespace std;

struct Unionfind{
    vector<int> data;
    Unionfind(int size):data(size, -1) {}
    bool unite(int x, int y){
        x=root(x);
        y=root(y);
        if(x!=y){
            if(data[y] < data[x]) swap(x, y);
            data[x] += data[y];
            data[y] = x;
        }
        return x!=y;
    }
    bool same(int x, int y){
        return root(x) == root(y);
    }
    int root(int x){
        return (data[x] < 0) ? x : data[x]=root(data[x]);
    }
    int size(int x){
        return -data[root(x)];
    }
};


signed main(){
    std::cin.tie(nullptr);
    std::ios_base::sync_with_stdio(false);
    int n,m; cin >> n >> m;
    vector<int> col(n,-1);
    vector<vector<Pii>> G(n);
    Unionfind uni(n);
    vector<int> use(n+1,1);
    rep(i,m){
        int u,v,c; cin >> u >> v >> c;
        u--; v--;
        if(!uni.same(u,v)){
            if(u==0||v==0){
                use[c]=0;
            }
            uni.unite(u,v);
            G[u].push_back({v,c});
            G[v].push_back({u,c});
        }
    }
    queue<int> q;
    q.push(0);
    while(!q.empty()){
        int fr=q.front();
        q.pop();
        for(auto u:G[fr]){
            if(col[u.first]==-1&&u.first!=0){
                if(col[fr]==u.second){
                    if(u.second==n) col[u.first] = u.second-1;
                    else col[u.first] = u.second+1;
                }else col[u.first]=u.second;
                q.push(u.first);
            }
        }
    }
    for(int i=1;i<=n;i++){
        if(use[i]){
            col[0]=i;
            break;
        }
    }
    rep(i,n){
        cout << col[i] << endl;
    }
    return 0;
}
// g++ main.cpp -o main.out && ./main.out