/**
 * Sergey Kopeliovich (burunduk30@gmail.com)
 */

#include <bits/stdc++.h>
#include "optimization.h"

using namespace std;

#define forn(i, n) for (int i = 0; i < (int)(n); i++)

int main() {
	int n = readInt();
	struct Edge {
		int a, b, w;
	};
	vector<Edge> e(n - 1);
	forn(i, n - 1) {
		int a = readInt() - 1;
		int b = readInt() - 1;
		int w = readInt();
		e[i] = {a, b, w};
	}
	deque<int> p;
	forn(i, n - 1)
		p.push_front(readInt() - 1);

	vector<int> d(n); // v --> root
	vector<int> pa(n);
	vector<vector<int>> ind(n);
	vector<unordered_map<int, int>> count(n);
	forn(i, n) {
		pa[i] = i;
		ind[i].push_back(i);
		count[i][0] = 1;
	}
	function<int(int)> get = [&](int v) {
		return v == pa[v] ? v : (pa[v] = get(pa[v]));
	};
	uint64_t ans = 0;
	vector<uint64_t> comp_ans(n);
	function<void(int, int, int)> add = [&](int p, int v, int D) {
		d[v] = D, pa[v] = p, ind[p].push_back(v);
		int da = count[p][D]++;
		ans += da, comp_ans[p] += da;
	};
	deque<uint64_t> answer = {0};
	for (int i : p) {
		auto sz = [&](int i) { return ind[get(i)].size(); };
		if (sz(e[i].a) > sz(e[i].b))
			swap(e[i].a, e[i].b);
		int root_a = get(e[i].a);
		int root_b = get(e[i].b);
		int D = d[e[i].a] ^ e[i].w ^ d[e[i].b];
		for (int v : ind[root_a]) // v --> root_a --> e[i].a --> e[i].b ---> root_b
			add(root_b, v, d[v] ^ D);
		answer.push_front(ans -= comp_ans[root_a]);
	}
	for (auto x : answer)
		writeInt(x, ' ');
}
