Problem:
Score : 400 points

Problem Statement

We have a tree with N vertices numbered 1 to N.
The i-th edge in the tree connects Vertex u_i and Vertex v_i, and its length is w_i.
Your objective is to paint each vertex in the tree white or black (it is fine to paint all vertices the same color) so that the following condition is satisfied:

For any two vertices painted in the same color, the distance between them is an even number.

Find a coloring of the vertices that satisfies the condition and print it. It can be proved that at least one such coloring exists under the constraints of this problem.

Constraints

All values in input are integers.

1 \leq N \leq 10^5

1 \leq u_i < v_i \leq N

1 \leq w_i \leq 10^9

Input

Input is given from Standard Input in the following format:

N
u_1 v_1 w_1
u_2 v_2 w_2
.
.
.
u_{N - 1} v_{N - 1} w_{N - 1}

Output

Print a coloring of the vertices that satisfies the condition, in N lines.
The i-th line should contain 0 if Vertex i is painted white and 1 if it is painted black.

If there are multiple colorings that satisfy the condition, any of them will be accepted.

Sample Input 1

3
1 2 2
2 3 1

Sample Output 1

0
0
1

Sample Input 2

5
2 5 2
2 3 10
1 3 8
3 4 2

Sample Output 2

1
0
1
0
1

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ContestLibrary;

namespace ABC126
{
    class D
    {
        static void Main(string[] args)
        {
            List<int> list = Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToList();
            int N = list[0];

            Graph g = new Graph(N, false);
            
            for (int i = 0; i < N - 1; i++)
            {
                List<int> list0 = Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToList();
                int u = list0[0], v = list0[1], w = list0[2];
                g.AddEdge(u, v, w);
            }

            double[] dis = g.Dijkstra(1);

            for(int i = 1; i <= N; i++)
            {
                int c = 0;
                if (dis[i] % 2 == 1)  c=1;
                Console.WriteLine(c);
            }

        }

    }

}

    namespace ContestLibrary
    {

        class Graph
        {
            public bool UseMatrix { get; set; }
            //private bool idZeroStart;
            public List<Vertex> Vertices { get; }
            public List<Edge> Edges { get; }
            public double[,] Matrix { get; private set; }
            public bool IsDirectedGraph { get; }

            //idは1,2,...,N
            public Graph(int N, bool isDirectedGraph = false, bool useMatrix = false)
            {
                IsDirectedGraph = isDirectedGraph;
                Vertices = new List<Vertex>();
                Edges = new List<Edge>();

                if (useMatrix) Matrix = new double[N, N];

                for (int i = 0; i < N; i++)
                {
                    int id = i + 1;
                    Vertex n = new Vertex(id);
                    Vertices.Add(n);
                }
            }

            //隣接行列方式でのセットアップ
            public void SetAdjancencyMatrix(double[,] matrix)
            {
                Matrix = matrix;

                if (matrix.GetLength(0) != Vertices.Count || matrix.GetLength(1) != Vertices.Count)
                {
                    throw new Exception("Invalid Matrix Size");
                }

                for (int i = 0; i < Vertices.Count; i++)
                {
                    Vertex vertexL = Vertices[i];
                    for (int j = 0; j < Vertices.Count; j++)
                    {
                        if (i > j && !IsDirectedGraph) continue;
                        if (matrix[i, j] != double.PositiveInfinity)
                        {
                            Vertex vertexR = Vertices[j];
                            Edge edge = new Edge(vertexL, vertexR, matrix[i, j], IsDirectedGraph);
                            Edges.Add(edge);
                        }
                    }
                }

            }


            //隣接リスト方式でのセットアップ
            public void AddAdjacencyList(int idVertex, Dictionary<int, double> adjDictionary)
            {
                int indexL = idVertex - 1;
                Vertex vertexL = Vertices[indexL];

                foreach (var v in adjDictionary)
                {
                    int idR = v.Key;
                    double weight = v.Value;
                    int indexR = idR - 1;
                    Vertex vertexR = Vertices[indexR];
                    Edge edge = new Edge(vertexL, vertexR, weight, IsDirectedGraph);
                    Edges.Add(edge);
                    if (Matrix != null)
                    {
                        Matrix[indexL, indexR] = weight;
                        if (!IsDirectedGraph) Matrix[indexR, indexL] = weight;
                    }
                }
            }
            public void AddAdjacencyList(int idVertex, List<int> adjList)
            {
                Dictionary<int, double> dic = new Dictionary<int, double>();
                foreach (int x in adjList)
                {
                    dic.Add(x, 1);
                }
                AddAdjacencyList(idVertex, dic);
            }

            //辺単位でのセットアップ
            public void AddEdge(int idL, int idR, int weight = 1)
            {
                int indexL = idL - 1;
                int indexR = idR - 1;

                Vertex vertexL = Vertices[indexL];
                Vertex vertexR = Vertices[indexR];
                Edge edge = new Edge(vertexL, vertexR, weight, IsDirectedGraph);
                Edges.Add(edge);
                if (Matrix != null)
                {
                    Matrix[indexL, indexR] = weight;
                    if (!IsDirectedGraph) Matrix[indexR, indexL] = weight;
                }
            }


            //開始点を指定し、幅優先探索で到達できる
            //各頂点に対応するステップ数（辺ウェイト考慮せず）と直近頂点IDのペアをDictionaryで出力
            public Dictionary<int, int[]> BreadthFirstSearch(int idS)
            {
                Dictionary<int, int[]> dic = new Dictionary<int, int[]>();
                int[] item = { 0, 0 };
                dic.Add(idS, item);
                int index = idS - 1;

                List<Vertex> nodes = new List<Vertex>();
                Vertex nodeStart = Vertices[index];
                nodeStart.Visited = true;
                nodes.Add(nodeStart);
                int depth = 1;
                while (nodes.Count > 0)
                {
                    List<Vertex> nextNodes = new List<Vertex>();
                    foreach (Vertex node in nodes)
                    {
                        foreach (Vertex cn in node.ConnectedVertices)
                        {
                            if (!cn.Visited)
                            {
                                nextNodes.Add(cn);
                                cn.Visited = true;
                                int[] nitem = { depth, node.Id };
                                dic.Add(cn.Id, nitem);
                            }
                        }
                    }
                    nodes = nextNodes;
                    depth++;
                }
                return dic;
            }

            //開始点を指定し、深さ優先探索
            //TimeFound(訪問時刻)とTimeProcessed(処理完了時刻)を出力
            public int DepthFirstSearch(int idS, int connectGraphNo = 1, int time = 0)
            {
                Stack<Vertex> stack = new Stack<Vertex>();
                int index = idS - 1;
                List<Vertex> nodes = new List<Vertex>();
                Vertex nodeStart = Vertices[index];
                nodeStart.Visited = true;

                stack.Push(nodeStart);
                nodeStart.TimeVisited = time;
                nodeStart.ConnectGraphNo = connectGraphNo;

                while (stack.Count > 0)
                {
                    Vertex v = stack.Peek();

                    if (v.IndexNextSearch >= v.ConnectedVertices.Count)
                    {
                        time++;
                        v.TimeProcessed = time;
                        stack.Pop();
                    }
                    else
                    {
                        Vertex vn = v.ConnectedVertices[v.IndexNextSearch];
                        if (!vn.Visited)
                        {
                            time++;
                            stack.Push(vn);
                            vn.Visited = true;
                            vn.TimeVisited = time;
                            vn.ConnectGraphNo = connectGraphNo;
                        }
                        v.IndexNextSearch++;
                    }
                }
                return time;
            }

            //全頂点を探索
            public void DFS()
            {
                int time = 1;
                int connectNo = 1;
                int index = 0;
                while (index < Vertices.Count)
                {
                    int id = index + 1;
                    time = DepthFirstSearch(id, connectNo, time);

                    while (index < Vertices.Count && Vertices[index].Visited) index++;
                    connectNo++;
                    time++;
                }
            }

            //二点間の最短経路を取得(幅優先探索の結果を利用)
            public List<Vertex> ShortestPath(int idS, int idT)
            {
                Dictionary<int, int[]> dic = BreadthFirstSearch(idS);
                List<int> plist = new List<int>();
                int p = idT;
                while (p != idS)
                {
                    p = dic[p][1];
                    plist.Add(p);
                }
                plist.Reverse();
                List<Vertex> vlist = new List<Vertex>();
                foreach (int id in plist)
                {
                    Vertex vp = Vertices[id - 1];
                    vlist.Add(vp);
                }
                Vertex vT = Vertices[idT - 1];
                vlist.Add(vT);
                return vlist;
            }


            //Prim法で最小全域木を作成し重みの総和を計算(PriorityQueueクラスを利用)
            //辺に着目するためO(m log(m))であまり早くないが殆どの場合十分と思われる
            public double MinimumSpanningTree()
            {
                //最初に選ぶ頂点は何でもよい
                Vertex v0 = Vertices[0];

                bool[] includedVertex = new bool[Vertices.Count + 1];
                double sumWeight = 0;

                //最小全域木に含まれるEdge
                List<Edge> mstEdges = new List<Edge>();
                //現在の木に隣接しているEdgeの優先度付きキュー
                PriorityQueue<Edge> pq = new PriorityQueue<Edge>();

                includedVertex[v0.Id] = true;
                foreach (Edge en in v0.ConnectedEdges)
                {
                    pq.Enqueue(en, -en.Weight);
                }

                int counter = 1;
                while (counter < Vertices.Count)
                {
                    Edge edge = pq.Dequeue();
                    Vertex v;
                    //既に両方の頂点が木に含まれているEdgeは除外（含むとループができてしまう)
                    if (includedVertex[edge.VertexL.Id] && includedVertex[edge.VertexR.Id]) continue;
                    else if (includedVertex[edge.VertexL.Id]) v = edge.VertexR;
                    else v = edge.VertexL;
                    mstEdges.Add(edge);
                    sumWeight += edge.Weight;
                    includedVertex[v.Id] = true;

                    //新しく木に隣接するようになったEdgeをキューに追加
                    foreach (Edge e1 in v.ConnectedEdges)
                    {
                        if (includedVertex[e1.VertexL.Id] && includedVertex[e1.VertexR.Id]) continue;
                        pq.Enqueue(e1, -e1.Weight);
                    }

                    counter++;
                }

                return sumWeight;
            }

            //O((|V|+|E|)ln(|V|)
            public double[] Dijkstra(int idS)
            {
                double[] distances = Enumerable.Repeat(double.PositiveInfinity, Vertices.Count + 1).ToArray();
                int index = idS - 1;
                distances[idS] = 0;

                Vertex v0 = Vertices[index];

                PriorityQueue<Vertex> pq = new PriorityQueue<Vertex>();
                pq.Enqueue(v0, 0);

                while (pq.Count > 0)
                {
                    Vertex v = pq.Dequeue();
                    foreach (Edge e in v.ConnectedEdges)
                    {
                        Vertex vn = e.VertexL == v ? e.VertexR : e.VertexL;
                        double distanceNew = distances[v.Id] + e.Weight;
                        if (distanceNew < distances[vn.Id])
                        {
                            distances[vn.Id] = distanceNew;
                            //distanceがより良い値に更新される時、
                            //同一のVertexが複数キューに入ることがあるが、
                            //先に入った（悪い方の）数値は必ず無視されるので問題ない
                            pq.Enqueue(vn, -distances[vn.Id]);
                        }
                    }
                }


                return distances;
            }

            //負閉路を含む場合戻り値False
            //有向グラフ限定 重みマイナスを許容,ネガティブループ検出　O(|V||E|)
            public bool BellmanFord(int idS, out double[] distances)
            {
                distances = Enumerable.Repeat(double.PositiveInfinity, Vertices.Count + 1).ToArray();
                int index = idS - 1;
                distances[idS] = 0;

                for (int i = 0; i < Vertices.Count - 1; i++)
                {
                    foreach (Edge e in Edges)
                    {
                        double dn = distances[e.VertexL.Id] + e.Weight;
                        if (dn < distances[e.VertexR.Id])
                        {
                            distances[e.VertexR.Id] = dn;
                        }
                    }
                }

                foreach (Edge e in Edges)
                {
                    if (distances[e.VertexR.Id] > distances[e.VertexL.Id] + e.Weight)
                    {
                        return false;
                    }
                }
                return true;
            }

            //全点対最短経路（ワ―シャル・フロイト） 要matrix O(N^3)
            public double[,] WarshallFloyd(out int[,] predecessorMatrix)
            {
                int N = Vertices.Count;
                double[,] d = (double[,])Matrix.Clone();

                int[,] p = new int[N, N]; //先行点行列
                for (int i = 0; i < N; i++)
                {
                    for (int j = 0; j < N; j++)
                    {
                        if (d[i, j] != double.PositiveInfinity && i != j)
                        {
                            p[i, j] = i + 1;
                        }
                    }
                }

                for (int k = 0; k < N; k++)
                {
                    double[,] dn = new double[N, N];
                    int[,] pn = new int[N, N];
                    for (int i = 0; i < N; i++)
                    {
                        for (int j = 0; j < N; j++)
                        {
                            if (i == j) continue;
                            //kを経由することで改善する場合
                            if (d[i, j] > d[i, k] + d[k, j])
                            {
                                dn[i, j] = d[i, k] + d[k, j];
                                pn[i, j] = p[k, j];
                            }
                            else
                            {
                                dn[i, j] = d[i, j];
                                pn[i, j] = p[i, j];
                            }
                        }
                    }
                    d = dn; p = pn;
                }
                predecessorMatrix = p;
                return d;
            }


        }

        class Vertex
        {
            public int Id { get; }
            public List<Edge> ConnectedEdges { get; private set; }
            public List<Vertex> ConnectedVertices { get; private set; }
            public bool Visited { get; set; }
            public int TimeVisited { get; set; }
            public int TimeProcessed { get; set; }
            public int IndexNextSearch { get; set; } //次に探索するVertex番号
            public int ConnectGraphNo { get; set; } //連結している頂点は同じ番号


            public Vertex(int id)
            {
                Id = id;
                ConnectedEdges = new List<Edge>();
                ConnectedVertices = new List<Vertex>();
            }


        }

        class Edge
        {
            public Vertex VertexL { get; }
            public Vertex VertexR { get; }
            public double Weight { get; }

            public Edge(Vertex vertexL, Vertex vertexR, double weight, bool isDirected)
            {
                VertexL = vertexL;
                VertexR = vertexR;
                vertexL.ConnectedEdges.Add(this);
                vertexL.ConnectedVertices.Add(vertexR);
                if (!isDirected)
                {
                    vertexR.ConnectedEdges.Add(this);
                    vertexR.ConnectedVertices.Add(vertexL);
                }
                Weight = weight;
            }
        }

        //優先度付きキュー（実装はヒープ)
        class PriorityQueue<T>
        {
            private List<HeapNode> heap = new List<HeapNode>();

            public int Count
            {
                get
                {
                    return heap.Count;
                }
            }

            public void Enqueue(T item, double priority)
            {
                HeapNode node = new HeapNode(item, priority);
                heap.Add(node);

                int index = heap.Count - 1;

                while (index > 0)
                {
                    int indexParent = (index - 1) / 2;
                    HeapNode parent = heap[indexParent];
                    if (priority > parent.Priority)
                    {
                        Swap(index, indexParent);
                        index = indexParent;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            public T Dequeue()
            {
                if (heap.Count == 0)
                {
                    throw new Exception("No item in priorityQueue");
                }

                T item = heap[0].Node;
                heap[0] = heap[heap.Count - 1];
                heap.RemoveAt(heap.Count - 1);
                if (heap.Count > 0)
                {
                    HeapNode node = heap[0];
                    int index = 0;
                    while (true)
                    {
                        int indexL = 2 * index + 1;
                        int indexR = 2 * index + 2;
                        if (indexL >= heap.Count) //子なし(Leaf)
                        {
                            break;
                        }
                        else //子が存在
                        {
                            HeapNode childBetter = heap[indexL];
                            int indexBetter = indexL;
                            if (indexR < heap.Count && heap[indexL].Priority < heap[indexR].Priority)
                            {
                                childBetter = heap[indexR];
                                indexBetter = indexR;
                            }

                            if (node.Priority < childBetter.Priority)
                            {
                                Swap(index, indexBetter);
                                //node = childBetter; 参照なのでスワップで自動的に子を参照してる
                                index = indexBetter;
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }
                return item;
            }

            public T Peek()
            {
                if (heap.Count == 0)
                {
                    throw new Exception("No item in priorityQueue");
                }
                return heap[0].Node;
            }

            private void Swap(int i, int j)
            {
                HeapNode hn = heap[i];
                heap[i] = heap[j];
                heap[j] = hn;
            }


            class HeapNode
            {
                public T Node { get; }
                public double Priority { get; }
                public HeapNode(T item, double priority)
                {
                    Node = item;
                    Priority = priority;
                }
            }

        }


    }