标签:
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2618 Accepted Submission(s): 922
思路:并查集;
我们用离线查询,然后将边按照升序排列,询问按照升序排列,然后我们可以用并查集维护联通的点,也就是本来不在同一个集合中的点只要有小于d的边就把他两合并,那么小于
d长度的点的组合,就是所有合法的集合求Cn2*2;
由于后面的d是比前面的大的所以前面我们所求得对后面的是有贡献的,我们就不需要从新循环找了
1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<stdlib.h> 5 #include<math.h> 6 using namespace std; 7 typedef long long LL; 8 int bin[30000]; 9 LL du[30000]; 10 typedef struct pp 11 { 12 int x; 13 int y; 14 int cost; 15 } ss; 16 typedef struct ak 17 { 18 int x; 19 int id; 20 } dd; 21 ss aa[200005]; 22 dd kk[6000]; 23 LL an[6000]; 24 bool cmp(pp p,pp q) 25 { 26 return p.cost<q.cost; 27 } 28 bool cmp1(dd p,dd q) 29 { 30 return p.x<q.x; 31 } 32 int main(void) 33 { 34 int i,j,k; 35 int n,m; 36 int ask; 37 scanf("%d",&k); 38 while(k--) 39 { 40 scanf("%d %d",&n,&m); 41 scanf("%d",&ask); 42 for(i=0; i<m; i++) 43 { 44 scanf("%d %d %d",&aa[i].x,&aa[i].y,&aa[i].cost); 45 } 46 for(i=0; i<ask; i++) 47 { 48 scanf("%d",&kk[i].x); 49 kk[i].id=i; 50 } 51 aa[m].cost=1e9; 52 sort(aa,aa+m,cmp); 53 sort(kk,kk+ask,cmp1); 54 for(i=0; i<=20000; i++) 55 { 56 du[i]=1; 57 bin[i]=i; 58 } 59 LL cnt=0; 60 int t=0; 61 for(i=0; i<=m; i++) 62 { 63 int x=aa[i].x; 64 int y=aa[i].y; 65 while(aa[i].cost>kk[t].x&&t<ask) 66 { 67 an[kk[t].id]=cnt; 68 t++; 69 } 70 if(t==ask) 71 break; 72 int xx,yy; 73 for(xx=x; xx!=bin[xx];) 74 { 75 xx=bin[xx]; 76 } 77 for(yy=y; yy!=bin[yy];) 78 { 79 yy=bin[yy]; 80 } 81 if(xx!=yy) 82 { 83 cnt=cnt-(LL)du[xx]*(LL)(du[xx]-1)/2; 84 cnt=cnt-(LL)du[yy]*(LL)(du[yy]-1)/2; 85 if(du[xx]>du[yy]) 86 { 87 du[xx]+=du[yy]; 88 bin[yy]=xx; 89 cnt+=(LL)du[xx]*(LL)(du[xx]-1)/2; 90 } 91 else 92 { 93 du[yy]+=du[xx]; 94 bin[xx]=yy; 95 cnt+=(LL)du[yy]*(LL)(du[yy]-1)/2; 96 } 97 } 98 } 99 for(i=0; i<ask; i++) 100 { 101 printf("%lld\n",an[i]*2); 102 } 103 } 104 return 0; 105 }
标签:
原文地址:http://www.cnblogs.com/zzuli2sjy/p/5538724.html