并查集加离线处理
#include<bits/stdc++.h>
using namespace std;
const int maxn=5000+10;
int f[20100];
int count1[maxn];
int num[4*maxn];
struct Edge{
int from,to,dis;
}e[100100];
struct node{
int num;
int index;
}ans[maxn];
bool cmp1(Edge a,Edge b){
return a.dis<b.dis;
}
bool cmp2(node a,node b){
return a.num<b.num;
}
int find(int x){
int k, j, r;
r = x;
while(r != f[r]) //查找跟节点
r = f[r]; //找到跟节点,用r记录下
k = x;
while(k != r) //非递归路径压缩操作
{
j = f[k]; //用j暂存parent[k]的父节点
f[k] = r; //parent[x]指向跟节点
k = j; //k移到父节点
}
return r; //返回根节点的值
}
void init(int n){
for(int i=1;i<=n;i++){
f[i]=i;
num[i]=1;
}
}
void mercy(int x,int y){
f[x]=y;
num[y]+=num[x];
}
int red()
{
char z=getchar();
while (z<'0' || z>'9') z=getchar();
int ans=0;
while (z>='0' && z<='9') {
ans=ans*10+z-'0';
z=getchar();
}
return ans;
}
int main(){
int t;
int n,m,k;
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&k);
init(n);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].dis);
sort(e+1,e+m+1,cmp1);
int num1;
for(int i=1;i<=k;i++){
scanf("%d",&num1);
ans[i].num=num1;
ans[i].index=i;
}
sort(ans+1,ans+k+1,cmp2);
int count_=1;
int flag=0;
for(int i=1;i<=m;){
if(e[i].dis<=ans[count_].num){
flag=0;
int x=find(e[i].from);
int y=find(e[i].to);
if(x!=y){
mercy(x,y);
}
i++;
}
else{
int ans1=0;
if(flag==0){
for(int j=1;j<=n;j++){
if(f[j]==j){
ans1+=num[j]*(num[j]-1);
}
}
count1[ans[count_].index]=ans1;
}
else{
count1[ans[count_].index]=count1[ans[count_-1].index];
}
flag=1;
count_++;
if(count_>k)
break;
}
}
if(count_<k){
for(int i=count_;i<=k;i++)
count1[ans[i].index]=n*(n-1);
}
for(int i=1;i<=k;i++)
printf("%d\n",count1[i]);
}
return 0;
}