#include <bits/stdc++.h>
using namespace std;
#include <math.h>
#include <iomanip>
#include <cstdint>
#include <string>
#include <sstream>
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
#define rep(i,n) for (int i = 0; i < (n); ++i)
typedef long long ll;
using P = pair<int,int>;
const int INF=1001001001;
const int mod =1e9+7;
vector<bool>seen;
vector<int>ans;
int N,M;
vector<vector<pair<int,int>>>G;
void dfs(int v){
  seen[v]=true;
  for(auto c:G[v]){
    if(seen[c.first]){continue;}
    else if(ans[v]==c.second){ans[c.first]=ans[v]%N+1;}
    else{ans[c.first]=c.second;}
    dfs(c.first);
  }
}
int main() {
  cin>>N>>M;
  ans.resize(N);
  G.resize(N);
  seen.resize(N,false);
  rep(i,M){
    int u,v,c;cin>>u>>v>>c;u--;v--;
    G[u].push_back({v,c});
    G[v].push_back({u,c});
  }
  ans[0]=1;
  dfs(0);
  rep(i,N){cout<<ans[i]<<endl;}
  return 0;
}
#include <bits/stdc++.h>
using namespace std;

struct UnionFind {
    vector<int> par;
    vector<int> siz;
    UnionFind(int N) : par(N),siz(N) {
        for (int i=0; i<N; i++) {
            par[i]=i,siz[i]=1;
        }
    }
    int root(int x) {
        if (par[x]==x) return x;
        return par[x]=root(par[x]);
    }
    void unite(int x, int y) {
        int rx=root(x);
        int ry=root(y);
        if (rx==ry) return;
        par[rx]=ry;
        siz[ry]+=siz[rx];
    }
    bool same(int x,int y) {
        int rx=root(x);
        int ry=root(y);
        return rx==ry;
    }
    int size (int x) {
        return siz[root(x)];
    }
};

int main() {
   int N,M;
   cin >> N >> M;
   vector<vector<pair<int,int>>> G(N);
   UnionFind tree(N);
   int A[N];
   memset(A,0,sizeof(A));
   for (int i=0; i<M; i++) {
       int u,v,c;
       cin >> u >> v >> c;
       if (tree.same(u-1,v-1)) continue;
       tree.unite(u-1,v-1);
       G[u-1].push_back({v-1,c});
       G[v-1].push_back({u-1,c});
   }
   queue<tuple<int,int,int>> q;
   for (int i=0; i<N; i++) {
       if (G[i].size()==1) {
           q.push(make_tuple(i,G[i][0].first,G[i][0].second));//position,position,distance
           A[i]=1;
           break;
       }
   }
   while (!q.empty()) {
       tuple<int,int,int> p=q.front();
       q.pop();
       int a=get<0>(p),b=get<1>(p),d=get<2>(p);
       if (d==A[a]) {
           if (d==1) A[b]=2;
           else A[b]=1;
       }
       else A[b]=d;
       for (auto x:G[b]) {
           int a=x.first;
           if (A[a]==0) {
               q.push(make_tuple(b,x.first,x.second));
           }
       }
   }
   for (int i=0; i<N; i++) cout << A[i] << endl;
}