description
analysis
-
排序+++并查集
-
把mmm条树边以及询问的qqq条边升序排序,然后离线做
-
对于当前的第iii条询问边,依次插入所有比当前边小于等于的树边,若两点不连通则按照两边节点数计算
-
这个用并查集维护一下连通的子树节点数,最后再排一次序输出
-
注意计算时判重
code
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 20005
#define MAXM 100005
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define O3 __attribute__((optimize("-O3")))
using namespace std;
ll fa[MAXN],size[MAXN];
ll n,m,q,test;
struct node
{
ll x,y,z;
}a[MAXM];
struct inquiry
{
ll x,y;
}b[MAXN],f[MAXN];
O3 inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
O3 inline bool cmp(node a,node b)
{
return a.z<b.z;
}
O3 inline bool cmp1(inquiry a,inquiry b)
{
return a.x<b.x;
}
O3 inline bool cmp2(inquiry a,inquiry b)
{
return a.y<b.y;
}
O3 inline ll getfa(ll x)
{
return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
O3 int main()
{
//freopen("T1.in","r",stdin);
test=read();
while (test--)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(f,0,sizeof(f));
memset(fa,0,sizeof(fa));
n=read(),m=read(),q=read();
fo(i,1,n)size[i]=1,fa[i]=i;
fo(i,1,m)a[i].x=read(),a[i].y=read(),a[i].z=read();
sort(a+1,a+m+1,cmp);
fo(i,1,q)b[i].x=read(),b[i].y=i;
sort(b+1,b+q+1,cmp1);
ll now=1,k=0;
fo(i,1,q)
{
f[i].x=f[i-1].x,f[i].y=b[i].y;
while (now<=m && a[now].z<=b[i].x)
{
ll x=getfa(a[now].x),y=getfa(a[now].y);
if (x!=y)
{
f[i].x=f[i].x-size[x]*(size[x]-1)-size[y]*(size[y]-1)+(size[x]+size[y])*(size[x]+size[y]-1);
fa[y]=x,size[x]+=size[y];
}
++now;
}
}
sort(f+1,f+q+1,cmp2);
fo(i,1,q)printf("%lld\n",f[i].x);
}
return 0;
}