// Original C++ solution (slower):
#include <iostream>

#include <string>

#include <vector>

#include <queue>

#include <set>

#include <map>

#include <utility>

#include <stack>

#include <numeric>

#include <algorithm>

#include <tuple>

#include <stdio.h>

#include <bitset>

#include <limits.h>

#include <complex>

#include <deque>

#include <iomanip>

#include <list>

#include <cstring>

using namespace std;

#define pi pair<int,int>

#define pl pair<long long,long long>

#define chmax(a,b) (a<b ? a=b:0)

#define chmin(a,b) (a>b ? a=b:0)

#define en cout << endl //セミコロンつけろ

//#define MM 1000000000

//#define MOD MM+7

typedef long long ll;

const int MM = 1e9;

const int MOD = MM+7;

const long double PI = acos(-1);

const long long INF = 1e15;

int dx[8] = {-1,0,1,0,-1,-1,1,1};

int dy[8] = {0,-1,0,1,-1,1,1,-1};

// 'A' = 65, 'Z' = 90, 'a' = 97, 'z' = 122

template<typename T>

T GCD(T u,T v){

    return v ? GCD(v,u%v) : u;

}

template<typename T>

T LCM(T x,T y){

    T gc = GCD(x,y);

    return x*y/gc;

}

struct edge {

    ll to,cost;

};

int color[100010]; 

void dfs(const vector<vector<edge> > g, int now){

    for (int i = 0; i < g[now].size(); i++){

        if (color[g[now][i].to] != -1) continue;



        if (color[now] == 0){

            if (g[now][i].cost % 2 == 1){

                color[g[now][i].to] = 1;

            } else if (g[now][i].cost % 2 == 0){

                color[g[now][i].to] = 0;

            }

        } else if (color[now] == 1){

            if (g[now][i].cost % 2 == 1){

                color[g[now][i].to] = 0;

            } else {

                color[g[now][i].to] = 1;

            }

        }

        dfs(g, g[now][i].to);

    }

}



// 0 - white, 1 - black

int main(){

    int N; cin >> N;

    vector<ll> u(N),v(N),w(N);

    vector<vector<edge> > g(N);

    fill(color,color+100010,-1);



    for (int i = 0; i < N-1; i++){

        cin >> u[i] >> v[i] >> w[i];

        u[i]--; v[i]--;

        w[i] %= 2;

        g[u[i]].push_back({v[i],w[i]});

        g[v[i]].push_back({u[i],w[i]});

    }

    //check

    //cout << "check" << endl;

    color[0] = 0;

    queue<ll> que;

    que.push(0);

    while(que.size()){

        ll q = que.front();

        que.pop();

        for (int i = 0; i < g[q].size(); i++){

            int tmp = g[q][i].to;

            if (color[tmp] != -1) continue;

        

            if (color[q] == 0){

                if (g[q][i].cost % 2 == 0){

                    color[g[q][i].to] = 0;

                } else {

                    color[g[q][i].to] = 1;

                }

            } else {

                if (g[q][i].cost % 2 == 0){

                    color[g[q][i].to] = 1;

                } else {

                    color[g[q][i].to] = 0;

                }

            }

            que.push(tmp);

        }

    }



    for (int i = 0; i < N; i++){

        if (color[i] == -1) cout << 1 << endl;

        else cout << color[i] << endl;

    }

}

// Optimized solution to the same problem (faster):
#include <iostream>

#include <string>

#include <vector>

#include <queue>

#include <set>

#include <map>

#include <utility>

#include <stack>

#include <numeric>

#include <algorithm>

#include <tuple>

#include <stdio.h>

#include <bitset>

#include <limits.h>

#include <complex>

#include <deque>

#include <iomanip>

#include <list>

#include <cstring>

using namespace std;

#define pi pair<int,int>

#define pl pair<long long,long long>

#define chmax(a,b) (a<b ? a=b:0)

#define chmin(a,b) (a>b ? a=b:0)

#define en cout << endl //セミコロンつけろ

//#define MM 1000000000

//#define MOD MM+7

typedef long long ll;

const int MM = 1e9;

const int MOD = MM+7;

const long double PI = acos(-1);

const long long INF = 1e15;

int dx[8] = {-1,0,1,0,-1,-1,1,1};

int dy[8] = {0,-1,0,1,-1,1,1,-1};

// 'A' = 65, 'Z' = 90, 'a' = 97, 'z' = 122

template<typename T>

T GCD(T u,T v){

    return v ? GCD(v,u%v) : u;

}

template<typename T>

T LCM(T x,T y){

    T gc = GCD(x,y);

    return x*y/gc;

}

struct edge {

    ll to,cost;

};

/*

const int COM_MAX = 500500;

long long fac[COM_MAX],finv[COM_MAX],inv[COM_MAX];

void init(){

    fac[0] = fac[1] = 1;

    finv[0] = finv[1] = 1;

    inv[1] = 1;

    for(int i = 2; i < COM_MAX; i++){

        fac[i] = fac[i-1]*i%MOD;

        inv[i] = MOD - inv[MOD%i]*(MOD/i)%MOD;

        finv[i] = finv[i-1]*inv[i]%MOD;

    }

}

long long COM(int n,int k){

    if(n < k || n < 0 || k < 0) return 0;

    return fac[n]*(finv[k]*finv[n-k]%MOD)%MOD;

}

*/



int main(){

    int N; cin >> N;

    vector<vector<edge> > g(N);

    vector<int> dist(N,-1);

    for (int i = 0; i < N-1; i++){

        ll u,v,w; cin >> u >> v >> w; u--; v--;

        g[u].push_back({v,w});

        g[v].push_back({u,w});

    }

    queue<int> que;

    que.push(0);

    dist[0] = 0;

    while (que.size()){

        int now = que.front();

        que.pop();

        for (auto e : g[now]){

            if (dist[e.to] != -1) continue;

            

            if (e.cost % 2 == 0){

                dist[e.to] = dist[now];

            } else {

                dist[e.to] = 1 - dist[now];

            }

            que.push(e.to);

        }

    }

    for (auto e : dist){

        if (e == -1) cout << 0 << endl;

        else cout << e << endl;

    }

}

// Fastest known solution for this problem: