// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

struct Fast {Fast() {std::cin.tie(0); ios::sync_with_stdio(false);}} fast;

using ll = long long;

using vi = vector<int>;

using vvi = vector<vi>;

using pii = pair<int, int>;

#define rep(i, n) for (int i = 0; i < (int)(n); i++)

#define all(x) (x).begin(),(x).end()

#define pb push_back

#define mp make_pair

#define MOD 1000000007



vector<pii> graph[100005]; //graph[i]の要素<j,w>は、iとjが隣接し距離wであることを表す

vi color(100005);

int B = 1, W = 0, yet = -1;



void dfs(int n, int s) {

    color[n] = s;

    for (auto val : graph[n]) {

        int m = val.first;

        int d = val.second;

        if (color[m] == (1 & (color[n] + d))) {

            continue;

        }

        else if (color[m] == -1) {

            dfs(m, (1 & (color[n] + d)));

        }

    }

}





int main() {

    int N;

    cin >> N;

    rep(i, N - 1) {

        int u, v, w;

        cin >> u >> v >> w;

        graph[u - 1].pb(mp(v - 1, (1 & w)));

        graph[v - 1].pb(mp(u - 1, (1 & w)));

    }

    color.assign(N, -1);



    rep(i, N) {

        if (color[i] != -1) {

            continue;

        }

        dfs(i, 0);

    }

    rep(i, N) cout << color[i] << endl;



}




// Faster C++ solution for the same problem (measured speedup: 3.873128677919458x):
#include <bits/stdc++.h>

using namespace std;



struct Benri { Benri() { std::cin.tie(0); ios::sync_with_stdio(false); cout << fixed << setprecision(12);}} benri;



using ll = long long;

using vi = vector<int>;

using vvi = vector<vi>;

using pii = pair<int, int>;

using vll = vector<long long>;

using pll = pair<ll, ll>;

using ull = unsigned long long;



template <typename T> using PQ = priority_queue<T>;

template <typename T> using minPQ = priority_queue<T, vector<T>, greater<T>>;



#define rep(i, n) for (int i = 0; i < (int)(n); i++)

#define all(x) (x).begin(),(x).end()

#define pb push_back

#define mp make_pair

#define F first

#define S second



template<class T>bool chmax(T &a, const T &b) { if (a < b) { a = b; return 1; } return 0; }

template<class T>bool chmin(T &a, const T &b) { if (b < a) { a = b; return 1; } return 0; }



constexpr long long MOD = 1000000007;

//constexpr long long MOD = 998244353;

//constexpr int INF = 1001001001;

constexpr ll INF = 1001001001001001001ll;

constexpr double EPS = 1e-10;

using number = long long;





struct UnionFind {

    vector<int> par, rank;



    UnionFind(int n) : par(n , -1), rank(n, 0) { }

    void init(int n) { par.assign(n, -1), rank.assign(n, 0); }



    int root(int x) {

        if (par[x] == -1) return x;

        else return par[x] = root(par[x]);

    }



    bool same(int x, int y) {

        return root(x) == root(y);

    }



    bool unite(int x, int y) {

        x = root(x); y = root(y);

        if (x == y) return false;

        if (rank[x] < rank[y]) swap(x, y);

        if (rank[x] == rank[y]) ++rank[x];

        par[y] = x;

        return true;

    }

};





int main() {

    int N; cin >> N;

    UnionFind uf(2 * N);

    rep(i, N - 1) {

        int a, b, w; cin >> a >> b >> w;

        a--; b--;

        if (w & 1) {

            uf.unite(a, b + N);

            uf.unite(a + N, b);

        }

        else {

            uf.unite(a, b);

            uf.unite(a + N, b + N);

        }

    }



    rep(i, N) {

        cout << (uf.same(0, i) ? 0 : 1) << endl;

    }

}