Problem:
Score : 500 points

Problem Statement

You are given a tree with N vertices 1,2,\ldots,N, and positive integers c_1,c_2,\ldots,c_N.
The i-th edge in the tree (1 \leq i \leq N-1) connects Vertex a_i and Vertex b_i.

We will write a positive integer on each vertex in T and calculate our score as follows:

On each edge, write the smaller of the integers written on the two endpoints.

Let our score be the sum of the integers written on all the edges.

Find the maximum possible score when we write each of c_1,c_2,\ldots,c_N on one vertex in T, and show one way to achieve it. If an integer occurs multiple times in c_1,c_2,\ldots,c_N, we must use it that number of times.

Constraints

1 \leq N \leq 10000

1 \leq a_i,b_i \leq N

1 \leq c_i \leq 10^5

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}
c_1 \ldots c_N

Output

Use the following format:

M
d_1 \ldots d_N

where M is the maximum possible score, and d_i is the integer to write on Vertex i.
d_1,d_2,\ldots,d_N must be a permutation of c_1,c_2,\ldots,c_N.
If there are multiple ways to achieve the maximum score, any of them will be accepted.

Sample Input 1

5
1 2
2 3
3 4
4 5
1 2 3 4 5

Sample Output 1

10
1 2 3 4 5

If we write 1,2,3,4,5 on Vertex 1,2,3,4,5, respectively, the integers written on the four edges will be 1,2,3,4, for the score of 10. This is the maximum possible score.

Sample Input 2

5
1 2
1 3
1 4
1 5
3141 59 26 53 59

Sample Output 2

197
59 26 3141 59 53

c_1,c_2,\ldots,c_N may not be pairwise distinct.

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

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

namespace {
    #define DUMPOUT cerr
    #ifndef DEBUG_
    #define dump(...)
    #else
    #define dump(...)                                                                       \
        DUMPOUT << "  ";                                                                    \
        DUMPOUT << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << endl; \
        DUMPOUT << "    ";                                                                  \
        dump_func(__VA_ARGS__)
    #endif
    void dump_func()
    {
        DUMPOUT << endl;
    }
    template <class Head, class... Tail>
    void dump_func(Head &&head, Tail &&... tail)
    {
        DUMPOUT << head;
        if (sizeof...(Tail) == 0)
        {
            DUMPOUT << " ";
        }
        else
        {
            DUMPOUT << ", ";
        }
        dump_func(std::move(tail)...);
    }
    template <class T>
    ostream &operator<<(ostream &os, const vector<T> &v)
    {
        for (auto i = begin(v); i != end(v); ++i)
            os << *i << (i == end(v) - 1 ? "" : " ");
        return os;
    }
    template <class T>
    void out2Dvector(vector<T> v)
    {
        for (const auto &vv : v)
            cout << vv << endl;
    }
    template <class T>
    istream &operator>>(istream &is, vector<T> &v)
    {
        for (auto i = begin(v); i != end(v); ++i)
            is >> *i;
        return is;
    }
    template <typename T, typename U>
    ostream &operator<<(ostream &os, pair<T, U> &pair_var)
    {
        os << "(" << pair_var.first << ", " << pair_var.second << ")";
        return os;
    }
    template <typename T, typename U>
    ostream &operator<<(ostream &os, map<T, U> &map_var)
    {
        os << "{";
        for (auto itr = map_var.begin(); itr != map_var.end(); itr++)
        {
            os << "(" << itr->first << ", " << itr->second << ")";
            itr++;
            if (itr != map_var.end())
                os << ", ";
            itr--;
        }
        os << "}";
        return os;
    }
    template <typename T>
    ostream &operator<<(ostream &os, set<T> &set_var)
    {
        os << "{";
        for (auto itr = set_var.begin(); itr != set_var.end(); itr++)
        {
            os << *itr;
            ++itr;
            if (itr != set_var.end())
                os << ", ";
            itr--;
        }
        os << "}";
        return os;
    }
} // namespace

namespace {
    using ull = unsigned long long;
    using ll = long long;
    using ld = long double;
    #define endl "\n"

    #define REP(i, n) for (ll i = 0; i < n; i++)
    #define REPR(i, n) for (ll i = n; i >= 0; i--)
    #define FOR(i, m, n) for (ll i = m; i < n; i++)
    #define even(x) (x) % 2 == 0
    #define odd(x) (x) % 2 != 0
    #define all(x) (x).begin(), (x).end()
    #define rall(x) (x).rbegin(), (x).rend()
    #define pcnt __builtin_popcount
    #define buli(x) __builtin_popcountll(x)
    #define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end());
    #define inp(t, x) \
        t x;          \
        cin >> x;
    #define ithBit(n, i) ((n) >> (i)&1)
    #define INIT()               \
        cin.tie(0);              \
        ios::sync_with_stdio(0); \
        cout << fixed << setprecision(20)

    // these functions return the position of result of Binary Search.
    #define LB(s, t, x) (int)(lower_bound(s, t, x) - s)
    #define UB(s, t, x) (int)(upper_bound(s, t, x) - s)

    #define M_PI 3.14159265358979323846
    ll qp(ll a, ll b, int mo)
    {
        ll ans = 1;
        do
        {
            if (b & 1)
                ans = 1ll * ans * a % mo;
            a = 1ll * a * a % mo;
        } while (b >>= 1);
        return ans;
    }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    ll lcm(ll a, ll b)
    {
        ll temp = gcd(a, b);
        return temp ? (a / temp * b) : 0;
    }
    int mDays[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
    int dx8[] = {1, -1, 0, 0, 1, 1, -1, -1}, dy8[] = {0, 0, -1, 1, -1, 1, -1, 1};

    template <typename F>
    class
    #if defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
        [[nodiscard]]
    #elif defined(__GNUC__) && __GNUC_PREREQ(3, 4)
        __attribute__((warn_unused_result))
    #endif // defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
        FixPoint : F {
            public :
                explicit constexpr FixPoint(F &&f) noexcept : F(std::forward<F>(f)) {}

            template <typename... Args>
            constexpr decltype(auto)
            operator()(Args &&... args) const {
                return F::operator()(*this, std::forward<Args>(args)...);
    } // namespace
    }
    ; // class FixPoint
    template <typename F>
    static inline constexpr decltype(auto)
    makeFixPoint(F &&f) noexcept
    {
        return FixPoint<F>{std::forward<F>(f)};
    }

    template <typename T>
    vector<T> make_v(size_t a) { return vector<T>(a); }
    template <typename T, typename... Ts>
    auto make_v(size_t a, size_t b, Ts... ts) { return vector<decltype(make_v<T>(b, ts...))>(a, make_v<T>(b, ts...)); }
    template <typename T, typename U, typename... V>
    typename enable_if<is_same<T, U>::value != 0>::type
    fill_v(U &u, const V... v) { u = U(v...); }
    template <typename T, typename U, typename... V>
    typename enable_if<is_same<T, U>::value == 0>::type
    fill_v(U &u, const V... v)
    {
        for (auto &e : u)
            fill_v<T>(e, v...);
    }

    template <class T>
    bool chmax(T &a, const T &b)
    {
        if (a < b)
        {
            a = b;
            return 1;
        }
        return 0;
    }
    template <class T>
    bool chmin(T &a, const T &b)
    {
        if (b < a)
        {
            a = b;
            return 1;
        }
        return 0;
    }

    inline bool rangeCheck2D(int nx, int ny, int Width, int Height) { return nx >= 0 and nx < Width and ny >= 0 and ny < Height; }

    int i_query(int a, int b)
    {
        cout << "? " << a << " " << b << endl;
        fflush(stdout);
        ll ret;
        cin >> ret;
        return ret;
    }

    void i_answer(vector<ll> ans)
    {
        cout << "! " << ans << endl;
        fflush(stdout);
    }
} // namespace

/*
    tuple binding
    auto [x, y] = make_tuple(0, 0);
    for pair
    auto [a, b] = pair<int, int>({v1, v2});

    bitset<N> bs(ini_val); // N must be constant
    bs.reset(); // reset all
*/

class ListG {
public:
    // there's directed edge between A and B
    // if to[A] has element B
    vector<vector<int>> to; 

    map<pair<int, int>, ll> cost;
    void setCost(int u, int v, ll c) { 
        cost[{min(u, v), max(u, v)}] = c;
    }
    ll getCost(int u, int v) {
        return cost[{min(u, v), max(u, v)}];
    }

    ListG(int s) : root(-1) {
        size = s;
        to = make_v<vector<int>>(size);
    }

    void setDirectedEdge(int f, int t) {
        to[f].push_back(t);
    }
    void setIndirectedEdge(int v1, int v2) {
        setDirectedEdge(v1, v2);
        setDirectedEdge(v2, v1);
    }

    void readGraph(int edgeNum, bool directed = false) {
        REP(i, edgeNum) {
            int u, v; cin >> u >> v; u--, v--;
            if (directed)
                setDirectedEdge(u, v);
            else
                setIndirectedEdge(u, v);
        }
    }

    void dfs(vector<char> &visiting, vector<char> &visited, int current, vector<vector<int>> &cloop) {
        for (auto&& next : to[current]) {
            if (visited[next]) continue;
            if (visiting[next]) {
                cloop[current].push_back(next);
                visited[next] = 1;
                dfs(visiting, visited, next, cloop);
                visited[next] = 0;
            } else {
                visiting[next] = 1;
                dfs(visiting, visited, next, cloop);
                visiting[next] = 0;
            }
        }
    }

    // return max depth
    int makeTree(int r) {
        root = r;
        p = make_v<int>(size);
        p[root] = -1;
        depth = make_v<int>(size);
        int maxDepth = 0;
        makeFixPoint([&](auto rec, int c, int d) -> void {
            depth[c] = d;
            chmax(maxDepth, d);
            REP(i, to[c].size()) {
                int next = to[c][i];
                if (p[c] == next) continue;
                p[next] = c;
                rec(next, d + 1);
            }
        })(root, 0);
        // count leaf node
        auto idxs = make_v<int>(size);
        iota(all(idxs), 0);
        leaf_idx = set<int>(all(idxs));
        REP(i, size) {
            if (i == root) continue;
            leaf_idx.erase(p[i]);
        }
        return maxDepth;
    }

    int diameterOfTree() {
        typedef pair<ll, int> Result;
        auto searchFarthest = makeFixPoint([&](auto searchFarthest, int p, int v) -> Result {
            Result r(0, v);
            for (const auto& next : to[v]) {
                if (next == p) continue;
                Result t = searchFarthest(v, next);
                t.first += 1;
                if (r.first < t.first)
                    r = t;
            }
            return r;
        });
        return searchFarthest(-1, 0).second;
    }

    pair<int, int> isBipartite() {
        auto color = make_v<int>(size);
        fill_v<int>(color, 0);

        auto rec = makeFixPoint([&](auto rec, int v, int c) -> bool {
            color[v] = c;
            for (const auto& next : to[v]) {
                if (color[next] == c)
                    return false;
                if (color[next] == 0 and not rec(next, -c))
                    return false;
            }
            return true;
        });

        pair<int, int> ret = {-1, -1};
        REP(i, size) {
            if (color[i] == 0)
                if (not rec(i, 1))
                    return ret;
        }
        ret = {0, 0};
        REP(i, size) {
            if (color[i] > 0) ret.first++;
            else ret.second++;
        }
        return ret;
    }

    void makeEulerTour() {
        assert(root >= 0);
        et_begin = make_v<int>(size);
        et_end = make_v<int>(size);
        tmp_k = 0;
        etdfs(root, -1);
    }

    vector<vector<int>> children() {
        assert(root >= 0);
        auto ret = make_v<vector<int>>(size);
        REP(i, size) {
            int prt = p[i];
            if (prt == -1) continue;
            ret[prt].push_back(i);
        }
        return ret;
    }

    // https://www.geeksforgeeks.org/strongly-connected-components/
    int stronglyConnectedConponent() {
        auto rto = make_v<vector<int>>(size);
        REP(from, size) {
            for (auto&& t : to[from])
                rto[t].push_back(from);
        }
        auto cmp = make_v<int>(size);
        fill_v<int>(cmp, 0);
        auto used = make_v<char>(size);
        fill_v<char>(used, 0);
        vector<int> rets; // return index in order
        REP(i, size) {
            makeFixPoint([&](auto dfs, int v) -> void {
                if (used[v]) return;
                used[v] = 1;
                for (auto&& t : to[v])
                    dfs(t);
                rets.push_back(v);
            })(i);
        }
        fill_v<char>(used, 0);
        int ret = 0;
        REPR(i, rets.size()-1) {
            makeFixPoint([&](auto rdfs, int v, int k) -> void {
                if (used[v]) return;
                used[v] = 1;
                cmp[v] = k;
                for (auto&& rt : rto[v])
                        rdfs(rt, k);
                
                rets.push_back(v);
            })(rets[i], ret++);
        }
        return ret;
    }

    vector<int> topologicalSorted() {
        vector<int> ret;
        auto used = make_v<char>(size);
        fill_v<char>(used, 0);
        REP(i, size) {
            makeFixPoint([&](auto dfs, int v) -> void {
                if (used[v]) return;
                used[v] = 1;
                for (auto&& t : to[v]) 
                    dfs(t);
                ret.push_back(v);
            })(i);
        }
        reverse(all(ret));
        return ret;
    }

    void dfsTree(ListG& dfst) {
        auto visited = make_v<char>(size);
        auto prt = make_v<int>(size);
        fill_v<char>(visited, 0);
        fill_v<int>(prt, 0);
        stack<int> st;
        st.push(0);
        while (st.size()) {
            int c = st.top(); st.pop();
            if (visited[c]) continue;
            visited[c] = 1;
            if (c != 0) dfst.setIndirectedEdge(c, prt[c]);
            for (const auto& next : to[c]) {
                prt[next] = c;
                st.push(next);
            }
        }
    }

    int size, root;
    vector<int> p; // parent for each node. parent of root = -1
    vector<int> depth; // for each node. depth of root node = 0
    vector<int> euler_tour;
    vector<int> et_begin, et_end;
    set<int> leaf_idx;

    int tmp_k;
private:
    void etdfs(int vidx, int pidx) {
        et_begin[vidx] = tmp_k;
        euler_tour.push_back(vidx);
        tmp_k++;
        REP(i, to[vidx].size()) {
            if (to[vidx][i] != pidx) {
                etdfs(to[vidx][i], vidx);
                euler_tour.push_back(vidx);
                tmp_k++;
            }
        }
        et_end[vidx] = tmp_k;
    }
};

int main(void)
{
    INIT(); // comment out for Interective Problem

    inp(ll, N);
    vector<pair<ll, int>> h(N);
    vector<pair<int, int>> ab(N-1);
    ListG lg(N);
    REP(i, N-1) {
        inp(int, a); inp(int, b);
        a--, b--;
        h[a].first++;
        h[b].first++;
        h[i+1].second = i+1;
        ab[i] = {a, b};
        lg.setIndirectedEdge(a, b);
    }
    
    vector<ll> c(N); cin >> c;
    sort(rall(c));
    int idx = 0;
    vector<ll> ans(N);
    queue<int> q;
    q.push(0);
    vector<bool> v(N);
    while (q.size()) {
        int current = q.front(); q.pop();
        v[current] = true;
        ans[current] = c[idx++];
        for (const auto& next : lg.to[current]) {
            if (v[next]) continue;
            q.push(next);
        }
    }
    ll sum = 0;
    REP(i, N-1) {
        sum += min(ans[ab[i].first], ans[ab[i].second]);
    }
    cout << sum << endl;
    cout << ans << endl;

    return 0;
}
//*/