#include "bits/stdc++.h"
using namespace std;
#define int               long long
#define pb                push_back
#define ppb               pop_back
#define pf                push_front
#define ppf               pop_front
#define all(x)            (x).begin(),(x).end()
#define uniq(v)           (v).erase(unique(all(v)),(v).end())
#define sz(x)             (int)((x).size())
#define fr                first
#define sc                second
#define pii               pair<int,int>
#define rep(i,a,b)        for(int i=a;i<b;i++)
#define mem1(a)           memset(a,-1,sizeof(a))
#define mem0(a)           memset(a,0,sizeof(a))
#define ppc               __builtin_popcount
#define ppcll             __builtin_popcountll

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
    cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args) {
    const char* comma = strchr(names + 1, ','); cerr.write(names, comma - names) << " : " << arg1 << " | "; __f(comma + 1, args...);
}

template<typename T1,typename T2>istream& operator>>(istream& in,pair<T1,T2> &a){in>>a.fr>>a.sc;return in;}
template<typename T1,typename T2>ostream& operator<<(ostream& out,pair<T1,T2> a){out<<a.fr<<" "<<a.sc;return out;}
template<typename T,typename T1>T amax(T &a,T1 b){if(b>a)a=b;return a;}
template<typename T,typename T1>T amin(T &a,T1 b){if(b<a)a=b;return a;}

const long long INF=1e18;
const int32_t M=1e9+7;
const int32_t MM=998244353;

const int N=100005;

map<pii,int> edgeid;
int edgelabel[N*2];
set<int> adj[N];
bool vis[N];
int vertexlabel[N];
void dfs(int v,int p=0){
	vis[v] = 1;
	if(!p||vertexlabel[p]==edgelabel[edgeid[{v,p}]]){
		vertexlabel[v] = 1;
		if(p&&vertexlabel[p]==1){
			vertexlabel[v]++;
		}
	}else vertexlabel[v] = edgelabel[edgeid[{v,p}]];
	for(auto u:adj[v]){
		if(vis[u])continue;
		dfs(u,v);
	}
}
void solve(){
	int n,m;
	cin>>n>>m;
	for (int i = 0; i < m; ++i) {
		int u,v,c;
		cin>>u>>v>>c;
		adj[u].insert(v);
		adj[v].insert(u);
		edgeid[{u,v}]=i+1;
		edgeid[{v,u}]=i+1;
		edgelabel[i+1]=c;
	}
	dfs(1);
	for (int i = 0; i < n; ++i) {
		cout<<vertexlabel[i+1]<<"\n";
	}
}
signed main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	#ifdef SIEVE
		sieve();
	#endif
	#ifdef NCR
		init();
	#endif
	int t=1;
	//cin>>t;
	while(t--) solve();
	return 0;
}

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
#define REP(i, n) for(int (i)=0; (i)< (n); ++i)
#define REPR(i, n) for(int (i)=(n); (i)>=0; --i)
#define FOR(i, n, m) for(int (i)=(n); (i)<(m); ++i)
constexpr int INF = 1e9;
//constexpr ll INF = 1LL << 61;
constexpr int mod = 1e9+7;

struct Edge{
  int x, y, d;
  Edge(){}
  Edge(int x, int y, int d): x(x), y(y), d(d){}
  bool operator< (const Edge l)const{
    return d < l.d;
  }
};

struct UnionFind{
  vector<int> node;
  UnionFind(int n){
    node = vector<int>(n, -1);
  }
  int find(int v){
    if(node[v] < 0){
      return v;
    }
    return node[v] = find(node[v]);
  }
  bool merge(int v, int u){
    int rootv = find(v);
    int rootu = find(u);
    if(rootv == rootu) return false;
    if(node[rootv] < node[rootu]){
      swap(rootv, rootu);
    }
    node[rootv] += node[rootu];
    node[rootu] = rootv;
    return true;
  }
  int size(int v){
    return -node[v];
  }
};
vector<int> ans;
void dfs(int v, vector<vector<pair<int, int>>> &g, int root){
  for(auto edge : g[v]){
    int nv = edge.first;
    int cost = edge.second;
    if(nv == root) continue;
    assert(nv != v);
    if(ans[v] == cost){
      if(cost ==0){
        ans[nv]= 1;
      }
      else{
        ans[nv] = 0;
      }
    }
    else{
      ans[nv] = cost;
    }
    dfs(nv, g, v);
  }
}
int main(){
  int N, M;
  cin >> N >> M;
  vector<Edge> edges(M);
  REP(i, M){
    int u, v, c;
    cin >> u >> v >> c;
    u--, v--, c--;
    edges[i] = Edge(u, v, c);
  }
  sort(edges.begin(), edges.end());
  vector<vector<pair<int, int>>> g(N);
  UnionFind uf(N);
  REP(i, M){
    int u, v;
    u = edges[i].x, v = edges[i].y;
    if(uf.merge(u, v)){
      g[v].push_back({u, edges[i].d});
      g[u].push_back({v, edges[i].d});
    }
  }
  ans.resize(N);
  ans[0] = 0;
  dfs(0, g, -1);
  REP(i, N){
    cout << ans[i]+1 << endl;
  }
  return 0;
}
