/*
题意: 给出一个L 找出有多少条路径符合条件(条件为路径中路的最大值《=L)
做了这个题学到了离线这个概念 离线就是 输入完成后进行操作 在线是变输入边操作
用并查集来构图 , 每当遇到2棵树合并时, num[x]*num[y]是新的路径数
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n,m,q;
int p[10010],num[10010];
struct E
{
int u,v,d;
bool operator <(const E & ss) const
{
return d<ss.d;
}
} a[50010];
struct QU
{
int id,l;
bool operator <(const QU & ss) const
{
return l<ss.l;
}
} b[10010];
int find(int x)
{
return p[x]==x?x:p[x]=find(p[x]);
}
int Union(int x,int y)
{
int px=find(x);
int py=find(y),t=0;
if(px!=py)
{
p[py]=px;
t=num[px]*num[py];
num[px]+=num[py];
}
return t;
}
int main()
{
while(scanf("%d%d%d",&n,&m,&q)!=EOF)
{
for(int i =0; i <= n; i++)
{
p[i] = i;
num[i] = 1;
}
for(int i = 0; i < m; i++)
scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].d);
for(int i = 0; i < q; i++)
{
scanf("%d",&b[i].l);
b[i].id = i;
}
sort(a,a+m);
sort(b,b+q);
int j = 0,ans=0,out[10010];
for(int i = 0; i < q; i++)
{
//printf("%d..\n",b[i].l);
while(j<m&&a[j].d<=b[i].l)
{
ans+=Union(a[j].u,a[j].v);
j++;
}
out[b[i].id]=ans;
}
for(int i = 0; i < q; i++)
printf("%d\n",out[i]);
}
return 0;
}