#include <stdio.h>
#include <assert.h>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <array>
#include <vector>
#include <queue>
#include <set>
#include <cmath>
#include <iomanip>
//#include <unordered_map>
//#include <unordered_set>
//#include <boost/container/static_vector.hpp>
//#include <boost/unordered_set.hpp>
//#include <boost/unordered_map.hpp>
//#include <unistd.h>

//#include <cv.h>
//#include <highgui.h>
#include <stdlib.h>
#include <string>

class Tree {
    public:
    struct Node {
        std::vector<int> edge;
        int rank; // ある頂点を根としたときのランク
        int partial_size; // ある頂点を根として、対象となる頂点を根とする部分木を構成した時のサイズ。
    };
    std::vector<Node> node;
    Tree() {}
    Tree(const int node_num_max) {
        node.resize(node_num_max);
    }
    void add_directed_edge(const int from, const int to) {
        node[from].edge.push_back(to);
    }
    void add_undirected_edge(const int node1, const int node2) {
        add_directed_edge(node1, node2);
        add_directed_edge(node2, node1);
    }
    void set_rank(int n, int rank, int parent) { // 辺が有向でも無向でも使える。呼び出すとき、parentは-1にしておくとよい。
        node[n].rank = rank;
        for (int c : node[n].edge) {
            if (c != parent) {
                set_rank(c, rank + 1, n);
            }
        }
    }
    void set_partial_size(int n, int parent) {
        node[n].partial_size = 1;
        for (int c : node[n].edge) {
            if (c != parent) {
                set_partial_size(c, n);
                node[n].partial_size += node[c].partial_size;
            }
        }
    }
    std::vector<int> get_children(int n) { // rankがセットされた前提で、頂点nの子
        std::vector<int> ret;
        for (int c : node[n].edge) {
            if (node[c].rank > node[n].rank) {
                ret.push_back(c);
            }
        }
        return ret;
    }
    std::vector<int> rank_descending_ids(int l, int r) { // [l, r]の数列を、ランクの高い順にまとめたベクトル。set_rankをした後であることが前提。
        std::vector<int> ret;
        for (int i = l; i <= r; i++) {
            ret.push_back(i);
        }
        std::sort(ret.begin(), ret.end(),
            [&](const int a, const int b) { return node[a].rank > node[b].rank; }
        );
        return ret;
    }
    int calc_diameter(int max_idx) {
        // 点は1～max_idxという想定。
        set_rank(1, 0, -1);
        int tmp_idx = 1;
        int tmp_diameter = 0;
        for (int i = 1; i <= max_idx; i++) {
            if (tmp_diameter < node[i].rank) {
                tmp_idx = i;
                tmp_diameter = node[i].rank;
            }
        }
        set_rank(tmp_idx, 0, -1);
        for (int i = 1; i <= max_idx; i++) {
            tmp_diameter = std::max(tmp_diameter, node[i].rank);
        }
        return tmp_diameter;
    }
};

const int MAX_N = 10050;
int N;
int a[MAX_N], b[MAX_N], c[MAX_N];
int ret[MAX_N];

Tree tree = Tree(MAX_N);

int main(int argc, char **argv) {
    std::cin >> N;

    for (int i = 1; i <= N - 1; i++) {
        std::cin >> a[i] >> b[i];
    }

    for (int i = 1; i <= N; i++) {
        std::cin >> c[i];
    }

    std::vector<int> cvec;
    for (int i = 1; i <= N; i++) {
        cvec.push_back(c[i]);
    }
    std::sort(cvec.begin(), cvec.end());

    for (int i = 1; i <= N - 1; i++) {
        tree.add_undirected_edge(a[i], b[i]);
    }
    tree.set_rank(1, 0, -1);

    std::vector<int> node_vec = tree.rank_descending_ids(1, N);

    for (int i = 0; i < N; i++) {
        ret[node_vec[i]] = cvec[i];
    }

    long long ret_val = 0;
    for (int i = 1; i <= N - 1; i++) {
        ret_val += std::min(ret[a[i]], ret[b[i]]);
    }

    std::cout << ret_val << std::endl;
    for (int i = 1; i <= N; i++) {
        std::cout << ret[i] << " ";
    }
    std::cout << std::endl;

    return 0;
}


Measured memory_bytes: 1536