0
题目描述很清楚。
1
①单纯并查集超时,要先用两个sort进行预处理。
②不能等并查集将每次所有的都合并完之后再计算,要一边合并一边计算!这个自己没想到,看了题解才知道!!
③注意!用sort按大小预处理时,用数组存储结果和对应提出的id(输入顺序),最后按照id输出结果!
2
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
struct Query{
int id;
int value;
bool operator <(const Query &a)const{
return value<a.value;
}
}qq[5010];
struct Edge{
int star;
int endd;
int value;
bool operator <(const Edge &a)const{
return value<a.value;
}
}edge[100010];
int res[5010];
int n,m,q;
int pre[20010];
int bj[20010];
int visted[20010];
long long int sum;
long long int cur;
int Find(int x){
int root=x;
while(root!=pre[root]){//while写成if,真是无语
root=pre[root];
}
while(pre[x]!=root){
int temp=pre[x];
pre[x]=root;
x=temp;
}
return root;
}
void Join(int a,int b){
int p1=Find(a);
int p2=Find(b);
if(p1==p2){
return;
}
int num1=visted[p1];
int num2=visted[p2];
sum+=(num1+num2)*(num1+num2-1)-num1*(num1-1)-num2*(num2-1);
if(visted[p1]>visted[p2]){
pre[p2]=p1;
visted[p1]+=visted[p2];
}
else{
pre[p1]=p2;
visted[p2]+=visted[p1];
}
}
int Bingcha(int x,int pos){
for(int i=pos;i<=m;i++){
if(edge[i].value<=x){
Join(edge[i].star,edge[i].endd);
}
if(edge[i].value>x){
pos=i;
break;
}
}
return pos;
}
int main()
{
int kase;
cin>>kase;
while(kase--){
sum=0;
scanf("%d%d%d",&n,&m,&q);
int t1;int t2;int t3;
int u=m;
int kk=1;
for(int i=1;i<=u;i++){
scanf("%d%d%d",&t1,&t2,&t3);
if(t1!=t2){
edge[kk].star=t1;
edge[kk].endd=t2;
edge[kk].value=t3;
kk++;
}
if(t1==t2){
m--;
}
}
sort(edge+1,edge+1+m);
int x;
for(int i=1;i<=q;i++){
scanf("%d",&qq[i].value);
qq[i].id=i;
}
sort(qq+1,qq+1+q);
for(int i=1;i<=n;i++){
pre[i]=i;
visted[i]=1;
bj[i]=0;
}
int pos=1;
for(int i=1;i<=q;i++){
pos=Bingcha(qq[i].value,pos);
res[qq[i].id]=sum;
}
for(int i=1;i<=q;i++){
cout<<res[i]<<endl;
}
}
return 0;
}