Problem:
Score : 600 points

Problem Statement

We have a tree with N vertices numbered 1 to N. The i-th edge in this tree connects Vertex a_i and b_i.
For each k=1, ..., N, solve the problem below:

Consider writing a number on each vertex in the tree in the following manner:

First, write 1 on Vertex k.

Then, for each of the numbers 2, ..., N in this order, write the number on the vertex chosen as follows:

Choose a vertex that still does not have a number written on it and is adjacent to a vertex with a number already written on it. If there are multiple such vertices, choose one of them at random.

Find the number of ways in which we can write the numbers on the vertices, modulo (10^9+7).

Constraints

2 \leq N \leq 2 \times 10^5

1 \leq a_i,b_i \leq N

The given graph is a tree.

Input

Input is given from Standard Input in the following format:

N
a_1 b_1
:
a_{N-1} b_{N-1}

Output

For each k=1, 2, ..., N in this order, print a line containing the answer to the problem.

Sample Input 1

3
1 2
1 3

Sample Output 1

2
1
1

The graph in this input is as follows:

For k=1, there are two ways in which we can write the numbers on the vertices, as follows:

Writing 1, 2, 3 on Vertex 1, 2, 3, respectively

Writing 1, 3, 2 on Vertex 1, 2, 3, respectively

Sample Input 2

2
1 2

Sample Output 2

1
1

The graph in this input is as follows:

Sample Input 3

5
1 2
2 3
3 4
3 5

Sample Output 3

2
8
12
3
3

The graph in this input is as follows:

Sample Input 4

8
1 2
2 3
3 4
3 5
3 6
6 7
6 8

Sample Output 4

40
280
840
120
120
504
72
72

The graph in this input is as follows:

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static System.Math;
using System.Text;
using System.Threading;
using System.Globalization;
using System.Runtime.CompilerServices;
using Library;

namespace Program
{
    public static class ProblemF
    {
        static bool SAIKI = false;
        static public int numberOfRandomCases = 0;
        static public void MakeTestCase(List<string> _input, List<string> _output, ref Func<string[], bool> _outputChecker)
        {
        }
        static public void Solve()
        {
            var N = NN;
            var ab = Repeat(0, N - 1).Select(_ => new { a = NN - 1, b = NN - 1 }).ToArray();
            var tree = new LIB_Tree(N);
            foreach (var item in ab)
            {
                tree.AddPath(item.a, item.b);
            }
            var dp = tree.LIB_ReRooting(_ => ((LIB_Mod)1, 1), (x, y) =>
            {
                var tot = x.Item2 + y.Item2;
                return (LIB_Mod.Comb(tot, x.Item2) * x.Item1 * y.Item1, tot);
            });
            dp.SetMergeVertexAndSubtree((v, t) => (t.Item1, t.Item2 + 1));
            dp.Build();
            for (var i = 0; i < N; i++)
            {
                Console.WriteLine(dp[i, -1].Item1);
            }
        }
        class Printer : StreamWriter
        {
            public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
            public Printer(Stream stream) : base(stream, new UTF8Encoding(false, true)) { base.AutoFlush = false; }
            public Printer(Stream stream, Encoding encoding) : base(stream, encoding) { base.AutoFlush = false; }
        }
        static LIB_FastIO fastio = new LIB_FastIODebug();
        static public void Main(string[] args) { if (args.Length == 0) { fastio = new LIB_FastIO(); Console.SetOut(new Printer(Console.OpenStandardOutput())); } if (SAIKI) { var t = new Thread(Solve, 134217728); t.Start(); t.Join(); } else Solve(); Console.Out.Flush(); }
        static long NN => fastio.Long();
        static double ND => fastio.Double();
        static string NS => fastio.Scan();
        static long[] NNList(long N) => Repeat(0, N).Select(_ => NN).ToArray();
        static double[] NDList(long N) => Repeat(0, N).Select(_ => ND).ToArray();
        static string[] NSList(long N) => Repeat(0, N).Select(_ => NS).ToArray();
        static long Count<T>(this IEnumerable<T> x, Func<T, bool> pred) => Enumerable.Count(x, pred);
        static IEnumerable<T> Repeat<T>(T v, long n) => Enumerable.Repeat<T>(v, (int)n);
        static IEnumerable<int> Range(long s, long c) => Enumerable.Range((int)s, (int)c);
        static IOrderedEnumerable<T> OrderByRand<T>(this IEnumerable<T> x) => Enumerable.OrderBy(x, _ => xorshift);
        static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> x) => Enumerable.OrderBy(x.OrderByRand(), e => e);
        static IOrderedEnumerable<T1> OrderBy<T1, T2>(this IEnumerable<T1> x, Func<T1, T2> selector) => Enumerable.OrderBy(x.OrderByRand(), selector);
        static IOrderedEnumerable<T> OrderByDescending<T>(this IEnumerable<T> x) => Enumerable.OrderByDescending(x.OrderByRand(), e => e);
        static IOrderedEnumerable<T1> OrderByDescending<T1, T2>(this IEnumerable<T1> x, Func<T1, T2> selector) => Enumerable.OrderByDescending(x.OrderByRand(), selector);
        static IOrderedEnumerable<string> OrderBy(this IEnumerable<string> x) => x.OrderByRand().OrderBy(e => e, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderByRand().OrderBy(selector, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<string> OrderByDescending(this IEnumerable<string> x) => x.OrderByRand().OrderByDescending(e => e, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<T> OrderByDescending<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderByRand().OrderByDescending(selector, StringComparer.OrdinalIgnoreCase);
        static string Join<T>(this IEnumerable<T> x, string separator = "") => string.Join(separator, x);
        static uint xorshift { get { _xsi.MoveNext(); return _xsi.Current; } }
        static IEnumerator<uint> _xsi = _xsc();
        static IEnumerator<uint> _xsc() { uint x = 123456789, y = 362436069, z = 521288629, w = (uint)(DateTime.Now.Ticks & 0xffffffff); while (true) { var t = x ^ (x << 11); x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); yield return w; } }
    }
}
namespace Library {
    partial struct LIB_Mod : IEquatable<LIB_Mod>, IEquatable<long>
    {
        static public long _mod = 1000000007; long v;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_Mod(long x)
        {
            if (x < _mod && x >= 0) v = x;
            else if ((v = x % _mod) < 0) v += _mod;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public implicit operator LIB_Mod(long x) => new LIB_Mod(x);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public implicit operator long(LIB_Mod x) => x.v;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Add(LIB_Mod x) { if ((v += x.v) >= _mod) v -= _mod; }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Sub(LIB_Mod x) { if ((v -= x.v) < 0) v += _mod; }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Mul(LIB_Mod x) => v = (v * x.v) % _mod;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Div(LIB_Mod x) => v = (v * Inverse(x.v)) % _mod;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public LIB_Mod operator +(LIB_Mod x, LIB_Mod y) { var t = x.v + y.v; return t >= _mod ? new LIB_Mod { v = t - _mod } : new LIB_Mod { v = t }; }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public LIB_Mod operator -(LIB_Mod x, LIB_Mod y) { var t = x.v - y.v; return t < 0 ? new LIB_Mod { v = t + _mod } : new LIB_Mod { v = t }; }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public LIB_Mod operator *(LIB_Mod x, LIB_Mod y) => x.v * y.v;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public LIB_Mod operator /(LIB_Mod x, LIB_Mod y) => x.v * Inverse(y.v);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public bool operator ==(LIB_Mod x, LIB_Mod y) => x.v == y.v;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public bool operator !=(LIB_Mod x, LIB_Mod y) => x.v != y.v;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public long Inverse(long x)
        {
            long b = _mod, r = 1, u = 0, t = 0;
            while (b > 0)
            {
                var q = x / b;
                t = u;
                u = r - q * u;
                r = t;
                t = b;
                b = x - q * b;
                x = t;
            }
            return r < 0 ? r + _mod : r;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool Equals(LIB_Mod x) => v == x.v;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool Equals(long x) => v == x;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override bool Equals(object x) => x == null ? false : Equals((LIB_Mod)x);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override int GetHashCode() => v.GetHashCode();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override string ToString() => v.ToString();
        static List<LIB_Mod> _fact = new List<LIB_Mod>() { 1 };
        static long _factm = _mod;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static void B(long n)
        {
            if (_factm != _mod) _fact = new List<LIB_Mod>() { 1 };
            if (n >= _fact.Count)
                for (int i = _fact.Count; i <= n; ++i)
                    _fact.Add(_fact[i - 1] * i);
            _factm = _mod;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public LIB_Mod Comb(long n, long k)
        {
            B(n);
            if (n == 0 && k == 0) return 1;
            if (n < k || n < 0) return 0;
            return _fact[(int)n] / _fact[(int)(n - k)] / _fact[(int)k];
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public LIB_Mod CombOK(long n, long k)
        {
            LIB_Mod ret = 1;
            for (var i = 0; i < k; i++) ret *= n - i;
            for (var i = 1; i <= k; i++) ret /= i;
            return ret;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public LIB_Mod Perm(long n, long k)
        {
            B(n);
            if (n == 0 && k == 0) return 1;
            if (n < k || n < 0) return 0;
            return _fact[(int)n] / _fact[(int)(n - k)];
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public LIB_Mod KanzenPerm(long n) => Enumerable.Range(0, (int)n + 1).Aggregate((LIB_Mod)0, (a, e) => a + (1 - ((e & 1) << 1)) * LIB_Mod.Comb(n, e) * LIB_Mod.Perm(n - e, n - e));
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static public LIB_Mod Pow(LIB_Mod x, long y)
        {
            LIB_Mod a = 1;
            while (y != 0)
            {
                if ((y & 1) == 1) a.Mul(x);
                x.Mul(x);
                y >>= 1;
            }
            return a;
        }
    }
    // copy key class LIB_ReRooting
    partial class /* not copy key */ LIB_Tree
    {
        /// <summary>
        /// 全方位木DP
        /// </summary>
        /// <param name="idxToVal">頂点番号から値を取得</param>
        /// <param name="mergeSubTrees">部分木と部分木のマージ (subtree, subtree)</param>
        /// <returns>2次元配列[node, parent]の部分木のDP値。parent=-1はnodeをルートとした木の値</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public CReRooting<T> LIB_ReRooting<T>(Func<long, T> idxToVal, Func<T, T, T> mergeSubTrees) => new CReRooting<T>(this, idxToVal, mergeSubTrees);
        public class CReRooting<T>
        {
            LIB_Tree tree;
            Dictionary<int, T>[] dp;
            Func<T, T, T> f;
            Func<long, T> g;
            Func<long, long, T, T> g2;
            Func<T, T, T> h;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public CReRooting(LIB_Tree tree, Func<long, T> idxToVal, Func<T, T, T> mergeSubTrees)
            {
                this.tree = tree;
                dp = Enumerable.Repeat(0, tree.N).Select(_ => new Dictionary<int, T>()).ToArray();
                f = mergeSubTrees;
                g = idxToVal;
                g2 = (r, p, v) => v;
                h = (v, t) => t;
            }
            public T this[long vtx, long parent]
            {
                [MethodImpl(MethodImplOptions.AggressiveInlining)]
                get { return dp[vtx][(int)parent]; }
            }
            /// <summary>
            /// 頂点番号(root, parent)で表す辺とrootをルートとする部分木をマージするメソッドを設定
            /// </summary>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public void SetMergeEdgeAndSubtree(Func<long, long, T, T> mergeEdgeAndSubtree) { g2 = mergeEdgeAndSubtree; }
            /// <summary>
            /// 頂点と部分木の結果をマージ(vertex, subtrees)するメソッドを設定
            /// </summary>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public void SetMergeVertexAndSubtree(Func<T, T, T> mergeVertexAndSubtree) { h = mergeVertexAndSubtree; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public void Build()
            {
                var done = new bool[tree.N];
                Action<long, long, T> upd = (vtx, rt, val) =>
                {
                    if (vtx == -1) return;
                    if (done[vtx]) dp[vtx][-1] = f(dp[vtx][-1], g2(rt, vtx, val));
                    else dp[vtx][-1] = g2(rt, vtx, val);
                    done[vtx] = true;
                };
                foreach (var item in tree.BFSFromLeaf(0))
                {
                    var ary = tree.path[item.node].Where(e => e != item.parent).ToArray();
                    var val = g(item.node);
                    if (ary.Length > 0)
                    {
                        var acc = g2(ary[0], item.node, dp[ary[0]][(int)item.node]);
                        foreach (var item2 in ary.Skip(1)) acc = f(acc, g2(item2, item.node, dp[item2][(int)item.node]));
                        val = h(val, acc);
                    }
                    upd(item.parent, item.node, dp[item.node][(int)item.parent] = val);
                }
                var swag = new LIB_SlidingWindowAggregation<T>(f);
                Action<int, int> process = (node, parent) =>
                {
                    var val = g(node);
                    if (tree.path[node].Count == 1)
                    {
                        var x = tree.path[node][0];
                        if (x != parent) upd(x, node, dp[node][x] = val);
                    }
                    else if (tree.path[node].Count == 2)
                    {
                        var x = tree.path[node][0]; var y = tree.path[node][1];
                        if (x != parent) upd(x, node, dp[node][x] = h(val, g2(y, node, dp[y][node])));
                        if (y != parent) upd(y, node, dp[node][y] = h(val, g2(x, node, dp[x][node])));
                    }
                    else if (tree.path[node].Count == 3)
                    {
                        var x = tree.path[node][0]; var y = tree.path[node][1]; var z = tree.path[node][2];
                        if (x != parent) upd(x, node, dp[node][x] = h(val, f(g2(y, node, dp[y][node]), g2(z, node, dp[z][node]))));
                        if (y != parent) upd(y, node, dp[node][y] = h(val, f(g2(x, node, dp[x][node]), g2(z, node, dp[z][node]))));
                        if (z != parent) upd(z, node, dp[node][z] = h(val, f(g2(x, node, dp[x][node]), g2(y, node, dp[y][node]))));
                    }
                    else if (tree.path[node].Count == 4)
                    {
                        var x = tree.path[node][0]; var y = tree.path[node][1]; var z = tree.path[node][2]; var w = tree.path[node][3];
                        var xy = f(g2(x, node, dp[x][node]), g2(y, node, dp[y][node]));
                        var zw = f(g2(z, node, dp[z][node]), g2(w, node, dp[w][node]));
                        if (x != parent) upd(x, node, dp[node][x] = h(val, f(g2(y, node, dp[y][node]), zw)));
                        if (y != parent) upd(y, node, dp[node][y] = h(val, f(g2(x, node, dp[x][node]), zw)));
                        if (z != parent) upd(z, node, dp[node][z] = h(val, f(xy, g2(w, node, dp[w][node]))));
                        if (w != parent) upd(w, node, dp[node][w] = h(val, f(xy, g2(z, node, dp[z][node]))));
                    }
                    else
                    {
                        swag.Clear();
                        var pre = new T[tree.path[node].Count];
                        for (var i = 0; i < pre.Length; ++i) swag.PushBack(pre[i] = g2(tree.path[node][i], node, dp[tree.path[node][i]][node]));
                        for (var i = 0; i < pre.Length; ++i)
                        {
                            var item2 = tree.path[node][i];
                            swag.PopFront();
                            if (item2 != parent) upd(item2, node, dp[node][item2] = h(val, swag.Aggregate()));
                            swag.PushBack(pre[i]);
                        }
                    }
                };
                foreach (var item in tree.BFSFromRoot(0)) process((int)item.node, (int)item.parent);
                for (var i = 1; i < tree.N; i++) dp[i][-1] = done[i] ? h(g(i), dp[i][-1]) : g(i);
            }
        }
    }
    class LIB_SlidingWindowAggregation<T>
    {
        T[][] list;
        T[][] agg;
        int[] size;
        Func<T, T, T> fun;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_SlidingWindowAggregation(IEnumerable<T> ary, Func<T, T, T> f)
        {
            list = new T[2][]; agg = new T[2][]; size = new int[2];
            fun = f;
            list[0] = new T[16]; agg[0] = new T[16]; size[0] = 0;
            if (ary.Any())
            {
                var temp = ary.ToArray();
                size[1] = temp.Length;
                list[1] = new T[size[1]];
                agg[1] = new T[size[1]];
                for (var i = 0; i < list[1].Length; i++)
                {
                    list[1][i] = temp[i];
                    if (i == 0) agg[1][i] = temp[i];
                    else agg[1][i] = fun(agg[1][i - 1], temp[i]);
                }
            }
            else
            {
                list[1] = new T[16]; agg[1] = new T[16]; size[1] = 0;
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_SlidingWindowAggregation(Func<T, T, T> f) : this(new T[0], f) { }
        public int Count => size[0] + size[1];
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Clear()
        {
            size[0] = size[1] = 0;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        void Push(int lista, T val)
        {
            if (list[lista].Length == size[lista])
            {
                var newAry = new T[size[lista] * 2];
                var newAgg = new T[size[lista] * 2];
                Array.Copy(list[lista], newAry, size[lista]);
                Array.Copy(agg[lista], newAgg, size[lista]);
                list[lista] = newAry;
                agg[lista] = newAgg;
            }
            if (size[lista] == 0) agg[lista][0] = val;
            else if (lista == 0) agg[lista][size[lista]] = fun(val, agg[lista][size[lista] - 1]);
            else agg[lista][size[lista]] = fun(agg[lista][size[lista] - 1], val);
            list[lista][size[lista]++] = val;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void PushBack(T val) => Push(1, val);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void PushFront(T val) => Push(0, val);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        T Pop(int lista)
        {
            var listb = 1 - lista;
            if (size[lista] == 0)
            {
                if (size[listb] == 0) throw new Exception();
                var mid = (size[listb] - 1) / 2;
                if (list[lista].Length <= mid)
                {
                    list[lista] = new T[mid + 1];
                    agg[lista] = new T[mid + 1];
                }
                size[lista] = 0;
                for (var i = mid; i >= 0; i--)
                {
                    if (size[lista] == 0) agg[lista][size[lista]] = list[listb][i];
                    else if (lista == 0) agg[lista][size[lista]] = fun(list[listb][i], agg[lista][size[lista] - 1]);
                    else agg[lista][size[lista]] = fun(agg[lista][size[lista] - 1], list[listb][i]);
                    list[lista][size[lista]++] = list[listb][i];
                }
                for (var i = mid + 1; i < size[listb]; i++)
                {
                    var idx = i - mid - 1;
                    if (idx == 0) agg[listb][idx] = list[listb][i];
                    else if (lista == 0) agg[listb][idx] = fun(list[listb][i], agg[listb][idx - 1]);
                    else agg[listb][idx] = fun(agg[listb][idx - 1], list[listb][i]);
                    list[listb][idx] = list[listb][i];
                }
                size[listb] -= size[lista];
            }
            return list[lista][--size[lista]];
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public T PopBack() => Pop(1);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public T PopFront() => Pop(0);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public T Aggregate()
        {
            if (size[0] == 0 && size[1] == 0) throw new Exception();
            else if (size[1] == 0) return agg[0][size[0] - 1];
            else if (size[0] == 0) return agg[1][size[1] - 1];
            else return fun(agg[0][size[0] - 1], agg[1][size[1] - 1]);
        }
    }
    class LIB_FastIO
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_FastIO() { str = Console.OpenStandardInput(); }
        readonly Stream str;
        readonly byte[] buf = new byte[1024];
        int len, ptr;
        public bool isEof = false;
        public bool IsEndOfStream
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get { return isEof; }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        byte read()
        {
            if (isEof) throw new EndOfStreamException();
            if (ptr >= len)
            {
                ptr = 0;
                if ((len = str.Read(buf, 0, 1024)) <= 0)
                {
                    isEof = true;
                    return 0;
                }
            }
            return buf[ptr++];
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        char Char()
        {
            byte b = 0;
            do b = read();
            while (b < 33 || 126 < b);
            return (char)b;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public string Scan()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
                sb.Append(b);
            return sb.ToString();
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public long Long()
        {
            long ret = 0; byte b = 0; var ng = false;
            do b = read();
            while (b != '-' && (b < '0' || '9' < b));
            if (b == '-') { ng = true; b = read(); }
            for (; true; b = read())
            {
                if (b < '0' || '9' < b)
                    return ng ? -ret : ret;
                else ret = ret * 10 + b - '0';
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public double Double() { return double.Parse(Scan(), CultureInfo.InvariantCulture); }
    }
    class LIB_FastIODebug : LIB_FastIO
    {
        Queue<string> param = new Queue<string>();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        string NextString() { if (param.Count == 0) foreach (var item in Console.ReadLine().Split(' ')) param.Enqueue(item); return param.Dequeue(); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_FastIODebug() { }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override string Scan() => NextString();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override long Long() => long.Parse(NextString());
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override double Double() => double.Parse(NextString());
    }
    partial class LIB_Tree
    {
        int N;
        List<int>[] path;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_Tree(long n)
        {
            N = (int)n;
            path = Enumerable.Repeat(0, N).Select(_ => new List<int>()).ToArray();
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddPath(long u, long v)
        {
            if (u >= N || v >= N) throw new Exception();
            path[u].Add((int)v);
            path[v].Add((int)u);
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public int[] GetSurround(long u) => path[u].ToArray();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public List<(long node, long parent)> BFSFromRoot(long root)
        {
            var bfsList = new List<(long node, long parent)>();
            var q = new Queue<int>();
            var done = new bool[N];
            bfsList.Add((root, -1));
            done[root] = true;
            q.Enqueue((int)root);
            while (q.Count > 0)
            {
                var w = q.Dequeue();
                foreach (var i in path[w])
                {
                    if (done[i]) continue;
                    done[i] = true;
                    q.Enqueue(i);
                    bfsList.Add((i, w));
                }
            }
            return bfsList;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public List<(long node, long parent)> BFSFromLeaf(long root) => BFSFromRoot(root).ToArray().Reverse().ToList();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public List<(long node, long parent, long direction)> EulerTour(long root)
        {
            var eulerList = new List<(long node, long parent, long direction)>();
            var s = new Stack<Tuple<int, int>>();
            var done = new bool[N];
            done[root] = true;
            s.Push(Tuple.Create((int)root, -1));
            while (s.Count > 0)
            {
                var w = s.Peek();
                var ad = true;
                foreach (var i in path[w.Item1])
                {
                    if (done[i]) continue;
                    done[i] = true;
                    ad = false;
                    s.Push(Tuple.Create(i, w.Item1));
                }
                if (!ad || path[w.Item1].Count == 1) eulerList.Add((w.Item1, w.Item2, 1));
                if (ad)
                {
                    s.Pop();
                    eulerList.Add((w.Item1, w.Item2, -1));
                }
            }
            return eulerList;
        }
    }
}