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# (Mono 4.6.2.0) (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 ABC160F
    {
        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 abList = Repeat(0, N - 1).Select(_ => new { a = NN, b = NN }).ToArray();
            var tree = new LIB_Tree(N);
            foreach (var item in abList)
            {
                tree.AddPath(item.a - 1, item.b - 1);
            }
            var rerooting = tree.ReRooting(
                e => new { cnt = 1, pat = (LIB_Mod)1 },
                (x, y) => new
                {
                    cnt = x.cnt + y.cnt,
                    pat = LIB_Mod.Comb(x.cnt + y.cnt, y.cnt) * x.pat * y.pat
                }
            );
            rerooting.SetMergeVertexAndSubtree(
                (x, y) => new
                {
                    cnt = y.cnt + 1,
                    pat = y.pat
                }
            );
            rerooting.Build();
            for (var i = 0; i < N; i++)
            {
                Console.WriteLine(rerooting[i, -1].pat);
            }
        }
        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())); } var t = new Thread(Solve, 134217728); t.Start(); t.Join(); 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 IEnumerable<T> OrderByRand<T>(this IEnumerable<T> x) => x.OrderBy(_ => xorshift);
        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 IEnumerable<string> OrderBy(this IEnumerable<string> x) => x.OrderBy(e => e, StringComparer.OrdinalIgnoreCase);
        static IEnumerable<T> OrderBy<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderBy(selector, StringComparer.OrdinalIgnoreCase);
        static IEnumerable<string> OrderByDescending(this IEnumerable<string> x) => x.OrderByDescending(e => e, StringComparer.OrdinalIgnoreCase);
        static IEnumerable<T> OrderByDescending<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderByDescending(selector, StringComparer.OrdinalIgnoreCase);
        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 {
    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 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;
        }
    }
    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
    {
        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 { get { return isEof; } }
        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++];
        }
        char Char()
        {
            byte b = 0;
            do b = read();
            while (b < 33 || 126 < b);
            return (char)b;
        }
        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();
        }
        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';
            }
        }
        virtual public double Double() { return double.Parse(Scan(), CultureInfo.InvariantCulture); }
    }
    class LIB_FastIODebug : LIB_FastIO
    {
        Queue<string> param = new Queue<string>();
        string NextString() { if (param.Count == 0) foreach (var item in Console.ReadLine().Split(' ')) param.Enqueue(item); return param.Dequeue(); }
        public LIB_FastIODebug() { }
        public override string Scan() => NextString();
        public override long Long() => long.Parse(NextString());
        public override double Double() => double.Parse(NextString());
    }
    class LIB_Tree
    {
        int N;
        List<int>[] path;
        public struct EulerRes
        {
            public long node;
            public long parent;
            public long direction;
        }
        List<EulerRes> eulerList;
        public struct BFSRes
        {
            public long node;
            public long parent;
        }
        List<BFSRes> bfsList;
        [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<BFSRes> BFSFromRoot(long root)
        {
            bfsList = new List<BFSRes>();
            var q = new Queue<int>();
            var done = new bool[N];
            bfsList.Add(new BFSRes { node = root, parent = -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(new BFSRes { node = i, parent = w });
                }
            }
            return bfsList;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public List<BFSRes> BFSFromLeaf(long root) => BFSFromRoot(root).ToArray().Reverse().ToList();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public List<EulerRes> EulerTour(long root)
        {
            eulerList = new List<EulerRes>();
            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(new EulerRes { node = w.Item1, parent = w.Item2, direction = 1 });
                if (ad)
                {
                    s.Pop();
                    eulerList.Add(new EulerRes { node = w.Item1, parent = w.Item2, direction = -1 });
                }
            }
            return eulerList;
        }
        public class LCAResult
        {
            int[] depth;
            int l;
            int[][] pr;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public LCAResult(int[] depth, int l, int[][] pr)
            {
                this.depth = depth;
                this.l = l;
                this.pr = pr;
            }
            public long this[long u, long v]
            {
                [MethodImpl(MethodImplOptions.AggressiveInlining)]
                get
                {
                    if (depth[u] > depth[v])
                    {
                        var t = u; u = v; v = t;
                    }
                    for (var k = 0; k < l; k++)
                    {
                        if ((((depth[v] - depth[u]) >> k) & 1) != 0) v = pr[k][v];
                    }
                    if (u == v) return u;
                    for (var k = l - 1; k >= 0; k--)
                    {
                        if (pr[k][u] != pr[k][v])
                        {
                            u = pr[k][u];
                            v = pr[k][v];
                        }
                    }
                    return pr[0][u];
                }
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LCAResult BuildLCA(long root)
        {
            var depth = new int[N];
            var l = 0;
            while (N > (1 << l)) l++;
            var pr = Enumerable.Repeat(0, l).Select(_ => new int[N]).ToArray();
            depth[root] = 0;
            pr[0][root] = -1;
            var q = new Stack<int>();
            q.Push((int)root);
            while (q.Count > 0)
            {
                var w = q.Pop();
                foreach (var i in path[w])
                {
                    if (i == pr[0][w]) continue;
                    q.Push(i);
                    depth[i] = depth[w] + 1;
                    pr[0][i] = w;
                }
            }
            for (var k = 0; k + 1 < l; k++)
            {
                for (var w = 0; w < N; w++)
                {
                    if (pr[k][w] < 0) pr[k + 1][w] = -1;
                    else pr[k + 1][w] = pr[k][pr[k][w]];
                }
            }
            return new LCAResult(depth, l, pr);
        }
        /// <summary>
        /// 蜈ｨ譁ｹ菴肴惠DP
        /// </summary>
        /// <param name="idxToVal">鬆らせ逡ｪ蜿ｷ縺九ｉ蛟､繧貞叙蠕・/param>
        /// <param name="mergeSubTrees">驛ｨ蛻・惠縺ｨ驛ｨ蛻・惠縺ｮ繝槭・繧ｸ (subtree, subtree)</param>
        /// <returns>2谺｡蜈・・蛻夕node, parent]縺ｮ驛ｨ蛻・惠縺ｮDP蛟､縲Ｑarent=-1縺ｯnode繧偵Ν繝ｼ繝医→縺励◆譛ｨ縺ｮ蛟､</returns>
        public CReRooting<T> 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);
            }
        }
    }
}