1 5 5 3 2 3 6334 1 5 15724 3 5 5705 4 3 12382 1 3 21726 6000 10000 13000
2 6 12
通过并查集计算新加入的,每次的计算公式为原来的s+合并后的两个集合数量乘积。。。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <stdio.h> #include <math.h> #include <string> #include <queue> #include <string.h> #include <map> #include <set> #include <vector> #include <algorithm> #include <stdlib.h> using namespace std; #define eps 1e-8 #define INF 20000000005 #define rd(x) scanf("%d",&x) #define rd2(x,y) scanf("%d%d",&x,&y) #define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z); #define rdLL(x) scanf("%I64d",&x) #define MAXn 20005 #define MAXe 100005 #define QUEnum 5005 struct Node{ int sta,end,val; }node[MAXe]; struct Que{ int queval , num; }que[QUEnum]; int sett[MAXn]; int sett_find(int x) { if(sett[x]<0) return x; return sett[x]=sett_find(sett[x]); } bool cmp1(Node a,Node b){ return a.val<b.val; } bool cmp2(Que a,Que b){ return a.queval<b.queval; } int main () { int Case; rd(Case); while(Case--) { memset(sett,-1,sizeof(sett)); int sum[MAXn]; int res[QUEnum]; for(int i=0;i<MAXn;i++) sum[i]=1; int n,e,quenum; rd3(n,e,quenum); for(int i=0;i<e;i++) rd3(node[i].sta,node[i].end,node[i].val); sort(node,node+e,cmp1); ///这里的排序不是+n 而是e 找了两个小时 for(int i=0;i<quenum;i++) { rd(que[i].queval); que[i].num=i; } sort(que,que+quenum,cmp2); int j=0,s=0; ///计数有多少能到达 for(int i=0 ; i<quenum ;i++) ///不能在这里添加j<e,因为大于的还需要计算 { while( j<e && node[j].val <= que[i].queval ){ int a=node[j].sta,b=node[j].end; int p = sett_find(a); int q = sett_find(b); if(p!=q){ s += (sum[q]*sum[p]); ////((sum[q]*(sum[q]+1))>>1) - ((sum[p]*(sum[p]+1))>>1) + sett[q] = p; sum[p]=sum[q]+sum[p]; ///p作为根节点 } j++; } res[ que[i].num ] = (s<<1); } for(int i=0;i<quenum;i++) printf("%d\n",res[i]); } return 0; }