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

template <typename T>
class Graph
{
public:
    struct Edge
    {
        long long to;
        T distance;
        Edge(long long t, T d)
        {
            to = t;
            distance = d;
        }
        bool operator<(const Edge &e) const
        {
            return distance < e.distance;
        }
        bool operator<=(const Edge &e) const
        {
            return distance <= e.distance;
        }
        bool operator>(const Edge &e) const
        {
            return distance > e.distance;
        }
        bool operator>=(const Edge &e) const
        {
            return distance >= e.distance;
        }
        bool operator==(const Edge &e) const
        {
            return distance == e.distance;
        }
    };
    vector<vector<T>> adjacency_matrix;
    long long node;
    T initial_value;
    vector<list<Edge>> edge;

    Graph(long long N)
    {
        setNode(N);
        initializeEdgeList();
    }

    Graph(long long N, T init)
    {
        setNode(N);
        initializeEdgeList();
        setInitialValue(init);
    }

    void setNode(long long N)
    {
        node = N + 1;
    }

    void setInitialValue(T init)
    {
        initial_value = init;
    }

    void initializeAdjacencyMatrix()
    {
        adjacency_matrix = vector<vector<T>>(
            node, vector<T>(node, initial_value));
    }

    void initializeAdjacencyMatrix(T init)
    {
        setInitialValue(init);
        initializeAdjacencyMatrix();
    }

    void initializeEdgeList()
    {
        edge = vector<list<Edge>>(node);
    }

    void updateAdjacencyMatrix(long long from, long long to, T distance)
    {
        adjacency_matrix[from][to] = distance;
    }

    void addEdge(long long from, long long to, T distance)
    {
        edge[from].push_back({to, distance});
    }

    // O(V^3)
    // CAUTION: Use adjacency matrix
    void runFloydWarshall()
    {
        for (long long i = 0; i < node; i++)
        {
            for (long long j = 0; j < node; j++)
            {
                for (long long k = 0; k < node; k++)
                {
                    adjacency_matrix[j][k] = min(
                        adjacency_matrix[j][k],
                        adjacency_matrix[j][i] + adjacency_matrix[i][k]);
                }
            }
        }
    }

    // O(VE)
    // CAUTION: Use edge list
    vector<T> runBellmanFord(long long from)
    {
        vector<T> distance(node, initial_value);
        distance[from] = 0;

        for (long long i = 0; i < node - 1; i++)
        {
            for (long long j = 1; j < node; j++)
            {
                for (auto itr = edge[j].begin(); itr != edge[j].end(); itr++)
                {
                    if (distance[itr->to] > distance[j] + itr->distance)
                    {
                        distance[itr->to] = distance[j] + itr->distance;
                    }
                }
            }
        }

        for (long long i = 1; i < node; i++)
        {
            for (auto itr = edge[i].begin(); itr != edge[i].end(); itr++)
            {
                if (distance[itr->to] > distance[i] + itr->distance)
                {
                    distance[0]--;
                }
            }
        }
        return distance;
    }

    // O(E + VlogV)
    // CAUTION: Use edge list
    vector<T> runDijkstra(long long from)
    {
        vector<T> distance(node, initial_value);
        priority_queue<Edge, vector<Edge>, greater<Edge>> queue;
        queue.push(Edge(from, 0));
        while (!queue.empty())
        {
            T d = queue.top().distance;
            long long to = queue.top().to;
            queue.pop();
            if (distance[to] == initial_value)
            {
                distance[to] = d;
                for (auto itr = edge[to].begin(); itr != edge[to].end(); itr++)
                {
                    if (distance[itr->to] == initial_value)
                    {
                        queue.push({itr->to, itr->distance + d});
                    }
                }
            }
        }
        return distance;
    }

    // O(ElogV)
    // CAUTION: Use adjacency matrix
    T runPrim()
    {
        vector<bool> is_visited(node, false);
        T cost = 0;
        priority_queue<Edge, vector<Edge>, greater<Edge>> queue;
        queue.push(Edge(1, 0));
        while (!queue.empty())
        {
            T distance = queue.top().distance;
            long long to = queue.top().to;
            queue.pop();
            if (!is_visited[to])
            {
                cost += distance;
                is_visited[to] = true;
                for (auto itr = edge[to].begin(); itr != edge[to].end(); itr++)
                {
                    queue.push({itr->to, itr->distance});
                }
            }
        }
        return cost;
    }

    T runKruskal()
    {
    }
};

int main()
{
    int N;
    cin >> N;

    Graph<int> g(N, -1);

    int u, v, w;
    for (int i = 0; i < N - 1; i++)
    {
        cin >> u >> v >> w;
        g.addEdge(u, v, w % 2);
        g.addEdge(v, u, w % 2);
    }

    vector<int> distance = g.runDijkstra(1);
    for (int i = 1; i <= N; i++)
    {
        cout << distance[i] % 2 << endl;
    }
}


Measured memory_bytes: 11776