思路:显然的mq这样的做法就T成狗...那么可以给边排个序,询问也排个序,然后扫过去,每次两个连通块合并的时候的答案就是(cnt[u]+cnt[v])*(cnt[u]+cnt[v]-1) - (cnt[u]*(cnt[u]-1))-(cnt[v]*(cnt[v]-1))嘛,然后就做完了
#include<bits/stdc++.h>
using namespace std;
const int maxn = 20000+6;
const int maxm = 100000+7;
int fa[maxn],cnt[maxn],ans[maxn];
int Find(int x){return x==fa[x]?x:fa[x]=Find(fa[x]);}
int n,m,qq;
struct Node
{
int u,v,w;
}e[maxm];
struct node
{
int w,id;
}q[maxn];
bool cmp1(node a,node b){return a.w<b.w;}
bool cmp(Node a,Node b){return a.w<b.w;}
void merge(int u,int v)
{
fa[u]=v;
cnt[v]+=cnt[u];
}
void init()
{
for(int i = 0;i<=n;i++)
{
fa[i]=i;
cnt[i]=1;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&qq);
init();
for(int i= 1;i<=m;i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
sort(e+1,e+1+m,cmp);
for(int i = 1;i<=qq;i++)
scanf("%d",&q[i].w),q[i].id=i;
sort(q+1,q+1+qq,cmp1);
int j = 1;
int res = 0;
for(int i = 1;i<=qq;i++)
{
while(j<=m && e[j].w<=q[i].w)
{
int u = Find(e[j].u);
int v = Find(e[j].v);
if(u!=v)
{
int tmp = cnt[u]+cnt[v];
res += (tmp*(tmp-1))-(cnt[u]*(cnt[u]-1))-(cnt[v]*(cnt[v]-1));
merge(u,v);
}
j++;
}
ans[q[i].id]=res;
}
for(int i = 1;i<=qq;i++)
printf("%d\n",ans[i]);
}
}