这场比赛其实打的还是比较傻逼的,赛后做总结,感觉麟哥和真珍姐讲的还是蛮有道理的,现在如果再做专题的话没有什么意义了,这段时间准备多做点套题。
比赛的时候并不是我写的这题,赛后补了一下,写离线并查集的话,不断插满足条件的边,如果是u,v在两棵不同子树的话,那么这次查找的答案就是ans += 2*cnt[findset(u)]*cnt[findset(v)];这里应该比较好理解。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define LL long long
#define FOR(i,x,y) for(int i = x;i < y;i ++)
#define IFOR(i,x,y) for(int i = x;i > y;i --)
#define N 20020
#define M 100010
#define Q 5005
using namespace std;
int n,m,q;
int fa[N];
int findset(int x) {return fa[x] != x ? fa[x] = findset(fa[x]) : x;}
struct Edge{
int u,v;
int val;
bool operator < (const Edge& rhs) const{
return val < rhs.val;
}
}edge[M];
struct Commend{
int x;
int id;
bool operator < (const Commend& rhs) const{
return x < rhs.x;
}
}cmd[Q];
int ans[Q];
int cnt[N];
int main()
{
//freopen("test.in","r",stdin);
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&q);
FOR(i,0,m){
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].val);
}
sort(edge,edge+m);
FOR(i,0,q){
scanf("%d",&cmd[i].x);
cmd[i].id = i;
}
sort(cmd,cmd+q);
FOR(i,1,n+1) {fa[i] = i;cnt[i] = 1;}
int op = 0;
int tem = 0;
FOR(i,0,q){
while(op < m && edge[op].val <= cmd[i].x){
int u = findset(edge[op].u),v = findset(edge[op].v);
op++;
if(u == v) continue;
tem += 2*cnt[u]*cnt[v];
fa[v] = u;
cnt[u] += cnt[v];
}
ans[cmd[i].id] = tem;
}
FOR(i,0,q){
printf("%d\n",ans[i]);
}
}
return 0;
}