1.题目描述:点击打开链接
2.解题思路:本题利用并查集解决,事先存储所有的查询,然后按照值由小到大排序,这样,可以计算出排序后的第i个查询比第i-1个查询增加的结点,比如如果u和v不在同一个集合,且此时u和v分别有rank[u]和rank[v]个元素,那么多增加的值就是2*rank[u]*rank[v]。累加ans即可。
3.代码:
#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cctype>
#include<complex>
#include<functional>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define me(s) memset(s,0,sizeof(s))
#define rep(i,n) for(int i=0;i<(n);i++)
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair <int, int> P;
const int maxn=20000+10;
const int maxm=100000+10;
int p[maxn];
int rnk[maxn];
int ans[5000+10];
int n,m,q;
struct Edge
{
int u,v;
int val;
void read()
{
scanf("%d%d%d",&u,&v,&val);
}
bool operator<(const Edge&rhs)const
{
return val<rhs.val;
}
}e[maxm];
struct Node
{
int id;
int x;
void read(int i)
{
id=i;
scanf("%d",&x);
}
}query[5000+10];
void init()
{
me(p);me(ans);
for(int i=1;i<=n;i++)
p[i]=i,rnk[i]=1;
}
int find(int x)
{
return p[x]==x?x:p[x]=find(p[x]);
}
void Union(int x,int y)
{
if(x==y)return;
if(rnk[x]>=rnk[y])
{
p[y]=x;
rnk[x]+=rnk[y];
}
else
{
p[x]=y;
rnk[y]+=rnk[x];
}
}
bool cmpx(Node a,Node b)
{
return a.x<b.x;
}
int bsearch(int st,int x)
{
int L=st,R=m-1;
while(L<R)
{
int M=L+(R-L+1)/2;
if(e[M].val<=x)L=M;
else R=M-1;
}
return L;
}
void solve()
{
int st=0;
for(int i=0;i<q;i++)
{
int id=query[i].id;
ans[id]=!i?0:ans[query[i-1].id];
int k=bsearch(st,query[i].x); //在[st,m)区间中进行查询
if(k>=m||e[k].val>query[i].x)continue;
for(int i=st;i<=k;i++)
{
int x=find(e[i].u),y=find(e[i].v);
if(x!=y)
{
ans[id]+=2*rnk[x]*rnk[y];
Union(x,y);
}
}
st=k+1;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&q);
init();
for(int i=0;i<m;i++)
e[i].read();
sort(e,e+m);
for(int i=0;i<q;i++)
query[i].read(i);
sort(query,query+q,cmpx);
solve();
for(int i=0;i<q;i++)
printf("%d\n",ans[i]);
}
}