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

typedef long long ll;
const int INF = 1e9 + 20;

int n;
int m[2];
int qnum;

struct node {
	node* c[2];
	node* p;
	bool flip;

	int idx;
	int val;
	node* max_node;

	int d() {
		assert(p);
		return p->c[1] == this;
	}

	bool r() {
		return !(p && p->c[d()] == this);
	}

	void do_flip() {
		flip = !flip;
	}

	void propagate() {
		if (flip) {
			flip = false;
			swap(c[0], c[1]);
			for (int i = 0; i < 2; i++) {
				if (c[i]) c[i]->do_flip();
			}
		}
	}

	void upd() {
		max_node = this;
		for (int i = 0; i < 2; i++) {
			if (c[i] && c[i]->max_node->val > max_node->val) {
				max_node = c[i]->max_node;
			}
		}
	}

	void propagate_all() {
		if (!r()) p->propagate_all();
		propagate();
	}

	void rot() {
		int x = d();
		node* pa = p;
		node* ch = c[!x];

		if (!pa->r()) pa->p->c[pa->d()] = this;
		p = pa->p;

		pa->c[x] = ch;
		if (ch) ch->p = pa;

		c[!x] = pa;
		pa->p = this;

		pa->upd();
		upd();
	}

	void splay() {
		propagate_all();
		while (!r()) {
			if (!p->r()) {
				if (p->d() == d()) p->rot();
				else rot();
			}
			rot();
		}
	}

	void expose() {
		splay();
		while (p) {
			p->splay();
			p->c[1] = this;
			rot();
		}
		c[1] = NULL;
		upd();
		assert(r());
	}

	void make_root() {
		expose();
		assert(r());
		do_flip();
	}

	void cut() {
		expose();
		assert(c[1] == NULL);
		assert(!flip);
		assert(c[0]);
		c[0]->p = NULL;
		c[0] = NULL;
		upd();
	}

	void link(node* v) {
		assert(get_root() != v->get_root());
		make_root();
		p = v;
	}

	node* get_root() {
		expose();
		node* v = this;
		while (true) {
			v->propagate();
			if (!v->c[0]) break;
			v = v->c[0];
		}
		v->expose();
		return v;
	}

	friend node* get_max(node* a, node* b) {
		assert(a && b);
		a->make_root();
		b->expose();
		assert(b->max_node);
		return b->max_node;
	}
};

struct edge {
	int a, b;
	int k;

	friend istream& operator >> (istream& i, edge& e) {
		cin >> e.a >> e.b >> e.k;
		e.a--; e.b--;
		return i;
	}

	bool operator < (const edge& o) const {
		return k < o.k;
	}
};
vector<edge> trees[2];
vector<edge> tree_mst[2];

vector<int> uf;
void reset_uf() {
	fill(uf.begin(), uf.end(), -1);
}
int getpar(int a) {
	return uf[a] < 0 ? a : (uf[a] = getpar(uf[a]));
}
bool unite(int a, int b) {
	a = getpar(a);
	b = getpar(b);
	if (a == b) return false;
	if (-uf[a] < -uf[b]) swap(a, b);
	uf[a] += uf[b];
	uf[b] = a;
	return true;
}

void solve_mst(vector<edge>& edges, vector<edge>& mst) {
	sort(edges.begin(), edges.end());
	reset_uf();
	for (int e = 0; e < int(edges.size()); e++) {
		if (unite(edges[e].a, edges[e].b)) {
			mst.push_back(edges[e]);
		}
	}
	assert(int(mst.size()) == n-1);
}

vector<node> vert_nodes;
vector<node> edge_nodes;

int main() {
	ios::sync_with_stdio(0), cin.tie(0);
	cin >> n >> m[0] >> m[1] >> qnum;
	uf.resize(n);
	for (int z = 0; z < 2; z++) {
		trees[z].resize(m[z]);
		for (int e = 0; e < m[z]; e++) {
			cin >> trees[z][e];
		}
		solve_mst(trees[z], tree_mst[z]);
	}

	vert_nodes.resize(n);
	for (int i = 0; i < n; i++) {
		vert_nodes[i].val = -INF;
		vert_nodes[i].idx = -1;
		vert_nodes[i].upd();
	}
	edge_nodes.resize(n-1);
	for (int e = 0; e < n-1; e++) {
		edge_nodes[e].val = tree_mst[0][e].k;
		edge_nodes[e].idx = e;
		edge_nodes[e].upd();
	}
	ll cur = 0;
	for (int e = 0; e < n-1; e++) {
		int a = tree_mst[0][e].a;
		int b = tree_mst[0][e].b;
		cur += tree_mst[0][e].k;
		vert_nodes[a].link(&edge_nodes[e]);
		vert_nodes[b].link(&edge_nodes[e]);
	}

	vector<int> ntr;
	ntr.reserve(n-1);
	for (int e = 0; e < n-1; e++) {
		int a = tree_mst[1][e].a;
		int b = tree_mst[1][e].b;
		node* max_path = get_max(&vert_nodes[a], &vert_nodes[b]);
		if (max_path->val == -INF) continue;
		int idx = max_path->idx;
		max_path->make_root();
		vert_nodes[tree_mst[0][idx].a].cut();
		vert_nodes[tree_mst[0][idx].b].cut();
		vert_nodes[a].link(&vert_nodes[b]);
		ntr.push_back(tree_mst[1][e].k - max_path->val);
	}
	sort(ntr.begin(), ntr.end());
	vector<pair<int, int> > queries(qnum);
	for (int i = 0; i < qnum; i++) {
		int t;
		cin >> t;
		queries[i] = make_pair(t, i);
	}
	sort(queries.begin(), queries.end());
	vector<ll> answers(qnum);
	for (int i = 0, j = 0; i < qnum; i++) {
		int t = queries[i].first;
		int idx = queries[i].second;
		while (j < int(ntr.size()) && ntr[j] <= 2*t) {
			cur += ntr[j];
			j++;
		}
		answers[idx] = cur + ll(t) * (-j + (n-1-j));
	}
	for (int i = 0; i < qnum; i++) {
		cout << answers[i] << '\n';
	}
}
