10 10 10 7 2 1 6 8 3 4 5 8 5 8 2 2 8 9 6 4 5 2 1 5 8 10 5 7 3 7 7 8 8 10 6 1 5 9 1 8 2 7 6
36 13 1 13 36 1 36 2 16 13
//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
//按照边大小排序,依次合并两端点,则以此边为路上最大长度
//的路径共有 num[x]*num[y];
//将要查询的L从小到大排序,依次处理即可
const int maxn=51000;
int fath[maxn];
int num[maxn];
int n;
void init()
{
for(int i=1;i<=n;i++) fath[i]=i,num[i]=1;
}
int find(int x)
{
return fath[x]==x?x:fath[x]=find(fath[x]);
}
int uion(int x,int y)
{
x=find(x),y=find(y);
if(x==y) return 0;
int cnt=num[x]*num[y];
if(num[x]<num[y])
{
fath[x]=y;
num[y]+=num[x];
}
else
{
fath[y]=x;
num[x]+=num[y];
}
return cnt;
}
struct Edge
{
int u,v,w;
};
Edge edge[maxn];
bool cmpEdge(Edge h,Edge k)
{
return h.w<k.w;
}
struct Node
{
int val;
int index;
};
Node ind[maxn];
bool cmpNode(Node h,Node k)
{
return h.val<k.val;
}
int ans[maxn];
int main()
{
int m,q;
while(scanf("%d%d%d",&n,&m,&q)==3)
{
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
}
sort(edge,edge+m,cmpEdge);
for(int i=0;i<q;i++)
{
scanf("%d",&ind[i].val);
ind[i].index=i;
}
sort(ind,ind+q,cmpNode);
init();
int sum=0;
int l=0;
for(int i=0;i<m;i++)
{
int u=edge[i].u,v=edge[i].v,w=edge[i].w;
int tmp=uion(u,v);
sum+=tmp;
while(l<q&&w>ind[l].val) ans[ind[l++].index]=sum-tmp;
}
for(int i=l;i<q;i++) ans[ind[i].index]=ans[ind[i-1].index];
for(int i=0;i<q;i++) printf("%d\n",ans[i]);
}
return 0;
}