#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
// x^1 = ~x
void dfs(const int cur, const vector<vector<int>>& vec, vector<bool>& viz,
vector<int>& st){
viz[cur] = true;
for(const auto next : vec[cur]){
if(!viz[next]){
dfs(next, vec, viz, st); } }
st.push_back(cur); }
void doi_sat(const vector<vector<int>>& vec, const vector<vector<int>>& vec_t, vector<bool>& rez){
const int n = vec.size();
vector<bool> viz(n, false);
vector<int> st;
for(int i = 0; i < n; ++i){
if(!viz[i]){
dfs(i, vec, viz, st); } }
fill(begin(viz), end(viz), false);
vector<int> comp;
while(!st.empty()){
const int cur = st.back();
st.pop_back();
if(!viz[cur]){
dfs(cur, vec_t, viz, comp);
if(all_of(begin(comp), end(comp), [&](const int x){ return !rez[x]; })){
for(const auto x : comp){
rez[x^1] = true; } } } } }
int main(){
ifstream f("andrei.in");
ofstream g("andrei.out");
int n, m;
f >> n >> m;
vector<vector<int>> vec(2*n), vec_t(2*n);
vector<bool> e_in_a(2*n, false);
auto add_muc = [&](const int surs, const bool v_surs, const int dest, const bool v_dest){
const int s = (2*surs) ^ (int)!v_surs, d = (2*dest) ^ (int)!v_dest;
vec[s^1].push_back(d);
vec[d^1].push_back(s);
vec_t[d].push_back(s^1);
vec_t[s].push_back(d^1); };
for(int i = 0, a, b, c; i < m; ++i){
f >> a >> b >> c;
--a, --b;
if(c == 0){
add_muc(a, 0, b, 0); }
if(c == 1){
add_muc(a, 1, b, 1); }
if(c == 2){
add_muc(a, 0, b, 0);
add_muc(a, 1, b, 1); } }
doi_sat(vec, vec_t, e_in_a);
for(int i = 0; i < n; ++i){
g << (e_in_a[2*i+1]) << ' '; }
return 0; }