Snuke Festival 2017 will be held in a tree with N vertices numbered 1,2, ...,N. The i-th edge connects Vertex a_i and b_i, and has joyfulness c_i.

The staff is Snuke and N-1 black cats. Snuke will set up the headquarters in some vertex, and from there he will deploy a cat to each of the other N-1 vertices.

For each vertex, calculate the niceness when the headquarters are set up in that vertex. The niceness when the headquarters are set up in Vertex i is calculated as follows:

* Let X=0.
* For each integer j between 1 and N (inclusive) except i, do the following:
* Add c to X, where c is the smallest joyfulness of an edge on the path from Vertex i to Vertex j.
* The niceness is the final value of X.

Constraints

* 1 \leq N \leq 10^{5}
* 1 \leq a_i,b_i \leq N
* 1 \leq c_i \leq 10^{9}
* The given graph is a tree.
* All input values are integers.

Input

Input is given from Standard Input in the following format:


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


Output

Print N lines. The i-th line must contain the niceness when the headquarters are set up in Vertex i.

Examples

Input

3
1 2 10
2 3 20


Output

20
30
30


Input

15
6 3 2
13 3 1
1 13 2
7 1 2
8 1 1
2 8 2
2 12 2
5 2 2
2 11 2
10 2 2
10 9 1
9 14 2
4 14 1
11 15 2


Output

16
20
15
14
20
15
16
20
15
20
20
20
16
15
20


Input

19
19 14 48
11 19 23
17 14 30
7 11 15
2 19 15
2 18 21
19 10 43
12 11 25
3 11 4
5 19 50
4 11 19
9 12 29
14 13 3
14 6 12
14 15 14
5 1 6
8 18 13
7 16 14


Output

103
237
71
263
370
193
231
207
299
358
295
299
54
368
220
220
319
237
370
#include <bits/stdc++.h>  
using namespace std;  
using ll = long long;  
using PII = pair<ll, ll>;  
#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)  
#define REP(i, n) FOR(i, 0, n)  
#define ALL(x) x.begin(), x.end()  
template<typename T> void chmin(T &a, const T &b) { a = min(a, b); }  
template<typename T> void chmax(T &a, const T &b) { a = max(a, b); }  
struct FastIO {FastIO() { cin.tie(0); ios::sync_with_stdio(0); }}fastiofastio;  
#ifdef DEBUG_   
#include "../program_contest_library/memo/dump.hpp"  
#else  
#define dump(...)  
#endif  
const ll INF = 1LL<<60;

template<class M>
struct RBST {
    using T = typename M::T;
    using E = typename M::E;

    struct node {
        node *l, *r, *p;
        T val, sum;
        E lazy;
        bool rev;
        int sz;

        node(T v, E p) : l(nullptr),r(nullptr),val(v),sum(v),lazy(p),rev(false),sz(1) {}
    };

    int size(node* a) { return !a ? 0 : a->sz; }
    T sum(node* a) { return !a ? M::dt() : (eval(a), a->sum); }
    node* fix(node* a) {
        a->sz = size(a->l) + 1 + size(a->r);
        a->sum = M::f(M::f(sum(a->l), a->val), sum(a->r));
        return a;
    }
    void eval(node* a) {
        if(a->lazy != M::de()) {
            a->val = M::g(a->val, a->lazy);
            a->sum = M::g(a->sum, M::p(a->lazy, a->sz));
            if(a->l) a->l->lazy = M::h(a->l->lazy, a->lazy);
            if(a->r) a->r->lazy = M::h(a->r->lazy, a->lazy);
            a->lazy = M::de();
        }
        if(a->rev) {
            swap(a->l, a->r);
            if(a->l) a->l->rev ^= 1;
            if(a->r) a->r->rev ^= 1;
            a->rev = false;
        }
    }

    inline int xor128() {
        static int x = 123456789, y = 362436069, z = 521288629, w = 88675123;
        int t;
        t = x ^ (x << 11); x = y; y = z; z = w;
        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
    }

    node* merge(node *a, node *b) {
        if(!a) return b;
        if(!b) return a;
        eval(a); eval(b);
        if(xor128() % (size(a) + size(b)) < size(a)) {
            a->r = merge(a->r, b);
            if(a->r) a->r->p = a;
            return fix(a);
        } else {
            b->l = merge(a, b->l);
            if(b->l) b->l->p = b;
            return fix(b);
        }
    }
    // [0,k) [k,n)
    pair<node*, node*> split(node *a, int k) {
        if(!a) return pair<node*, node*>(nullptr, nullptr);
        eval(a);
        node *sl, *sr;
        if(k <= size(a->l)) {
            tie(sl, sr) = split(a->l, k);
            if(a->l) a->l->p = nullptr;
            a->l = sr;
            if(a->l) a->l->p = a;
            return pair<node*, node*>(sl, fix(a));
        }
        tie(sl, sr) = split(a->r, k - size(a->l) - 1);
        if(a->r) a->r->p = nullptr;
        a->r = sl;
        if(a->r) a->r->p = a;
        return pair<node*, node*>(fix(a), sr);
    }
    // 要素の挿入/削除
    void insert(node*& a, int k, const T& x) {
        node *sl, *sr;
        tie(sl, sr) = split(a, k);
        a = merge(sl, merge(new node(x, M::de()), sr));
    }
    T erase(node*& a, int k) {
        node *sl, *sr, *tl, *tr;
        tie(sl, sr) = split(a, k + 1);
        tie(tl, tr) = split(sl, k);
        a = merge(tl, sr);
        return tr->val;
    }
    // 点代入
    void set_element(node*& a, int k, const T& x) {
        node *sl, *sr, *tl, *tr;
        tie(sl, sr) = split(a, k + 1);
        tie(tl, tr) = split(sl, k);
        if(tr) tr->val = tr->sum = x;
        a = merge(merge(tl, tr), sr);
    }
    // 区間更新
    void update(node*& a, int l, int r, const E& m) {
        node *sl, *sr, *tl, *tr;
        tie(sl, sr) = split(a, r);
        tie(tl, tr) = split(sl, l);
        if(tr) tr->lazy = M::h(tr->lazy, m);
        a = merge(merge(tl, tr), sr);
    }
    // 点取得
    T get(node*& a, int k) {
        node *sl, *sr, *tl, *tr;
        tie(sl, sr) = split(a, k + 1);
        tie(tl, tr) = split(sl, k);
        T res = !tr ? M::dt() : tr->val;
        a = merge(merge(tl, tr), sr);
        return res;
    }
    // 区間クエリ
    T query(node*& a, int l, int r) {
        node *sl, *sr, *tl, *tr;
        tie(sl, sr) = split(a, r);
        tie(tl, tr) = split(sl, l);
        T res = !tr ? M::dt() : tr->sum;
        a = merge(merge(tl, tr), sr);
        return res;
    }
    // 区間[l,r)の反転
    void reverse(node*& a, int l, int r) {
        node *sl, *sr, *tl, *tr;
        tie(sl, sr) = split(a, r);
        tie(tl, tr) = split(sl, l);
        if(tr) tr->rev ^= 1;
        a = merge(merge(tl, tr), sr);
    }
    // 頂点aが属する木の根を求める
    node* getroot(node *a) {
        if(!a->p) return a;
        return getroot(a->p);
    }
    // x以上の最小の位置
    int lower_bound(node *t, const T &x) {
        if(!t) return 0;
        if(x <= t->val) return lower_bound(t->l, x);
        return lower_bound(t->r, x) + size(t->l) + 1;
    }
    // xより大きい最小の位置
    int upper_bound(node *t, const T &x) {
        if(!t) return 0;
        if(x < t->val) return upper_bound(t->l, x);
        return upper_bound(t->r, x) + RBST<T>::size(t->l) + 1;
    }
    // xの個数
    int count(node *t, const T &x) {
        return upper_bound(t, x) - lower_bound(t, x);
    }
    // k番目の要素を求める
    T kth_element(node *t, int k) {
        if(k < RBST<T>::size(t->l)) return kth_element(t->l, k);
        if(k == RBST<T>::size(t->l)) return t->val;
        return kth_element(t->r, k - RBST<T>::size(t->l) - 1);
    }
    // 要素xを追加する
    void insert_key(node *&t, const T &x) {
        RBST<T>::insert(t, lower_bound(t, x), x);
    }
    // 要素xを消す
    void erase_key(node *&t, const T &x) {
        if(!count(t, x)) return;
        RBST<T>::erase(t, lower_bound(t, x));
    }
    // デバッグ用
    void debug(node* t) {
        if(t == nullptr) return;
        cerr << "{";
        debug(t->l);
        cerr << " " << t->val << " ";
        debug(t->r);
        cerr << "}";
    }

    void dfs(node *a) {
        eval(a);
        if(a->l) dfs(a->l);
        if(a->r) dfs(a->r);
    }
};

struct UnionFind {
    vector<int> par, s;
    UnionFind(int n=2e5) { init(n); }
    void init(int n) { 
        s.assign(n, 1); par.resize(n); 
        iota(par.begin(), par.end(), 0);
    }
    int find(int x) {
        if(par[x] == x) return x;
        return par[x] = find(par[x]);
    }
    void unite(int x, int y) {
        x = find(x);
        y = find(y);
        if(x == y) return;
        if(s[x] < s[y]) par[x] = y, s[y] = s[x] + s[y];
        else par[y] = x, s[x] = s[x] + s[y];
    }
    bool same(int x, int y) { return find(x) == find(y); }
    int size(int x) { return s[find(x)]; }
};

signed main() {
    ll n;
    cin >> n;
    vector<ll> a(n-1), b(n-1), c(n-1);
    REP(i, n-1) {
        cin >> a[i] >> b[i] >> c[i];
        a[i]--, b[i]--;
    }

    struct monoid {
        using T = ll;
        using E = ll;
        static T dt() { return 0; }
        static constexpr E de() { return 0; }
        static T f(const T &a, const T &b) {
            return a+b;
        }
        static T g(const T &a, const E &b) {
            return a+b;
        }
        static E h(const E &a, const E &b) {
            return a+b;
        }
        static E p(const E &a, const int &b) {
            return a*b;
        } 
    };
    RBST<monoid> tree;
    vector<RBST<monoid>::node*> nodes(n);
    REP(i, n) nodes[i] = new RBST<monoid>::node(0, 0);

    vector<ll> ord(n-1);
    iota(ALL(ord), 0);
    sort(ALL(ord), [&](ll l, ll r){
        return c[l] > c[r];
    });

    UnionFind uf(n);
    for(auto i: ord) {
        // b[i] と連結なやつには a[i]の連結成分のサイズ*c[i] を足す
        {
            auto r = tree.getroot(nodes[b[i]]);
            r->lazy += uf.size(a[i]) * c[i];
        }
        // a[i] と連結なやつ
        {
            auto r = tree.getroot(nodes[a[i]]);
            r->lazy += uf.size(b[i]) * c[i];
        }
        // a[i] と b[i] をつなぐ
        {
            auto u = tree.getroot(nodes[a[i]]), v = tree.getroot(nodes[b[i]]);
            tree.merge(u, v);
            uf.unite(a[i], b[i]);
        }

        auto r = tree.getroot(nodes[a[i]]);
        auto p = tree.split(r, tree.size(r)/2);
        tree.merge(p.first, p.second);
    }

    auto root = tree.getroot(nodes[0]);
    tree.dfs(root);

    vector<ll> ans(n);
    REP(i, n) ans[i] = nodes[i]->val;
    REP(i, n) cout << ans[i] << "\n";
    cout << flush;

    return 0;
}
