#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 100005, MAXM = 300005, MAXK = 22;
struct Edge {
int u, v, w, id;
bool operator<(const Edge& o) const { return w < o.w; }
} old_edges[MAXM];
int N, M, K;
ll pop[MAXN]; // ??????
int new_u[MAXK], new_v[MAXK];
// ???
struct DSU {
int parent[MAXN];
void init(int n) { for(int i=1;i<=n;++i) parent[i]=i; }
int find(int x) { return parent[x]==x ? x : parent[x]=find(parent[x]); }
bool unite(int x,int y) { x=find(x); y=find(y); if(x==y) return 0; parent[y]=x; return 1; }
};
// MST ???
struct TreeEdge { int to, id; };
vector<TreeEdge> tree[MAXN];
int depth[MAXN], up[MAXN][18], max_edge_id[MAXN][18];
ll sub_pop[MAXN]; // ?????
int edge_to_parent[MAXN]; // ???????id
int edge_w[MAXM]; // ????
ll edge_pop[MAXM]; // ???????????
// DFS ???????????????id?????
void dfs(int u, int p, int d) {
depth[u] = d;
up[u][0] = p;
for (int i = 1; i < 18; ++i) {
up[u][i] = up[ up[u][i-1] ][i-1];
int mid = up[u][i-1];
int e1 = max_edge_id[u][i-1];
int e2 = max_edge_id[mid][i-1];
max_edge_id[u][i] = (edge_w[e1] >= edge_w[e2]) ? e1 : e2;
}
for (size_t i = 0; i < tree[u].size(); ++i) {
int v = tree[u][i].to;
if (v == p) continue;
edge_to_parent[v] = tree[u][i].id;
max_edge_id[v][0] = tree[u][i].id;
dfs(v, u, d + 1);
sub_pop[u] += sub_pop[v];
}
}
// ????(u,v)??????????id
int query_max_edge(int u, int v, int& max_id) {
if (depth[u] < depth[v]) swap(u, v);
int diff = depth[u] - depth[v];
max_id = 0; edge_w[0] = 0; // ??????0
for (int i = 0; diff; ++i, diff >>= 1)
if (diff & 1) {
if (edge_w[max_edge_id[u][i]] > edge_w[max_id])
max_id = max_edge_id[u][i];
u = up[u][i];
}
if (u == v) return edge_w[max_id];
for (int i = 17; i >= 0; --i)
if (up[u][i] != up[v][i]) {
if (edge_w[max_edge_id[u][i]] > edge_w[max_id]) max_id = max_edge_id[u][i];
if (edge_w[max_edge_id[v][i]] > edge_w[max_id]) max_id = max_edge_id[v][i];
u = up[u][i]; v = up[v][i];
}
if (edge_w[max_edge_id[u][0]] > edge_w[max_id]) max_id = max_edge_id[u][0];
if (edge_w[max_edge_id[v][0]] > edge_w[max_id]) max_id = max_edge_id[v][0];
return edge_w[max_id];
}
int main() {
scanf("%d %d %d", &N, &M, &K);
for (int i = 1; i <= M; ++i) {
scanf("%d %d %d", &old_edges[i].u, &old_edges[i].v, &old_edges[i].w);
old_edges[i].id = i;
edge_w[i] = old_edges[i].w;
}
for (int i = 0; i < K; ++i)
scanf("%d %d", &new_u[i], &new_v[i]);
for (int i = 1; i <= N; ++i)
scanf("%lld", &pop[i]);
// ???????????
sort(old_edges + 1, old_edges + M + 1);
DSU dsu; dsu.init(N);
for (int i = 1; i <= M; ++i) {
if (dsu.unite(old_edges[i].u, old_edges[i].v)) {
int u = old_edges[i].u, v = old_edges[i].v;
int id = old_edges[i].id;
tree[u].push_back({v, id});
tree[v].push_back({u, id});
}
}
// DFS ?????1???
for (int i = 1; i <= N; ++i) sub_pop[i] = pop[i];
dfs(1, 0, 0);
// ?????????????????????
for (int i = 2; i <= N; ++i) {
int eid = edge_to_parent[i];
edge_pop[eid] = sub_pop[i];
}
// ????????????????id
int best_id[MAXK];
ll revenue[MAXK];
for (int i = 0; i < K; ++i) {
int mx_id = 0;
/* int mx_w = */ query_max_edge(new_u[i], new_v[i], mx_id);
best_id[i] = mx_id;
revenue[i] = (ll)edge_w[mx_id] * edge_pop[mx_id];
}
// ??????????????
ll best_income = 0;
int total = 1 << K;
for (int mask = 0; mask < total; ++mask) {
bool conflict = false;
ll sum = 0;
for (int i = 0; i < K; ++i) if (mask & (1 << i)) {
for (int j = i + 1; j < K; ++j) if (mask & (1 << j)) {
if (best_id[i] == best_id[j]) { conflict = true; break; }
}
if (conflict) break;
sum += revenue[i];
}
if (!conflict && sum > best_income)
best_income = sum;
}
printf("%lld\n", best_income);
return 0;
}