#include <bits/stdc++.h>

#ifdef DEBUG
#define PRINT(x)\
    cout<<"func "<<__func__<<": line "<<__LINE__<<": "<<#x<<" = "<<(x)<<endl;
#define PRINTA(a,first,last)\
    cout<<"func "<<__func__<<": line "<<__LINE__<<": "<<#a<<"["<<(first)<<", "<<(last)<<")"<<endl;\
    for (int i=(first);i<(last);++i){cout<<#a<<"["<<i<<"] = "<<(a)[i]<<endl;}
#define PRINTP(p)\
    cout<<"func "<<__func__<<": line "<<__LINE__<<": "<<#p<<" = ("<<(p.first)<<", "<<(p.second)<<")"<<endl;
#define PRINTI(a,i)\
    cout<<"func "<<__func__<<": line "<<__LINE__<<": "<<#a<<"["<<#i<<"] = "<<#a<<"["<<(i)<<"] = "<<(a)[i]<<endl;
#else
#define PRINT(x)
#define PRINTA(a,first,last)
#define PRINTP(p)
#define PRINTI(a,i)
#endif

#define FOR(i,a,b) for (int i=(a);i<(b);++i)
#define RFOR(i,a,b) for (int i=(b)-1;i>=(a);--i)
#define REP(i,n) for (int i=0;i<(n);++i)
#define RREP(i,n) for (int i=(n)-1;i>=0;--i)
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(),(a).end()
#define MOD 1000000007

using namespace std;

using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;

template <class T, class U> void amax(T& x, U y) {if (x < y) x = y;}
template <class T, class U> void amin(T& x, U y) {if (x > y) x = y;}

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

template <class T>
struct edge {
    size_t to;
    T cost;
    edge(size_t to, T cost = 1) : to(to), cost(cost) {}
};

template <class T>
class graph {
private:
    const size_t count_nodes;
    const bool is_directed;
public:
    vector<edge<T>> *edges;
    graph(size_t count_nodes, bool is_directed = true) : count_nodes(count_nodes), is_directed(is_directed) {
        edges = new vector<edge<T>>[count_nodes];
    }
    ~graph() {
        delete [] edges;
    }
    size_t size() const { return count_nodes; }
    void make_edge(size_t u, size_t v, T cost) {
        edges[u].push_back(edge<T>(v, cost));
        if (!is_directed)
            edges[v].push_back(edge<T>(u, cost));
    }
};

template <class T>
vector<T> dijkstra(const graph<T> &g, const int start) {
    vector<T> dist(g.size());
    bool *used = new bool[g.size()]();
    priority_queue<pair<T, size_t>, vector<pair<T, size_t>>, greater<pair<T, size_t>>> q;
    dist[start] = 0;
    q.push(pair<T, size_t>(dist[start], start));
    used[start] = true;
    while (!q.empty()) {
        T dist_v;
        size_t v;
        tie(dist_v, v) = q.top();
        q.pop();
        if (dist[v] < dist_v)
            continue;
        for (edge<T> e: g.edges[v]) {
            size_t w = e.to;
            T dist_v_w = dist_v + e.cost;
            if (!used[w] || dist[w] > dist_v_w) {
                dist[w] = dist_v_w;
                q.push(pair<T, size_t>(dist[w], w));
                used[w] = true;
            }
        }
    }
    delete [] used;
    return dist;
}

int main() {
    int N;
    cin >> N;
    graph<ll> g(N, false);
    REP(i, N - 1) {
        ll u, v, w;
        cin >> u >> v >> w;
        u--;
        v--;
        g.make_edge(u, v, w);
    }
    auto dist = dijkstra(g, 0);
    REP(i, N) {
        cout << (dist[i] % 2 == 0) << endl;
    }
    return 0;
}



Measured memory_bytes: 8812