http://acm.hdu.edu.cn/showproblem.php?pid=5441
题目大意是给一个n个城市(点)m条路线(边)的双向的路线图,每条路线有时间值(带权图),然后q个询问,每个询问一个时间值
求不大于这个时间的可以连通的城市有多少种连法
比如样例中第一个询问6000,不大于6000时间值的连通城市有3,5.所以有3-->5,5-->3两种
第二个询问10000,符合条件的连通的城市有2,3,5,所以有2-->3,3-->2,2-->5,5-->2,3-->5,5-->3六种
利用结构体储存点与权值然后把权值排序,找出符合条件的城市点,利用并查集记录相连的点然后合并,整合路线
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int father[20001],num[20001]; 6 int a[20001]; 7 void lsy(int n) 8 { 9 for (int i=1;i<=n;i++) 10 { 11 father[i]=i; 12 num[i]=1; 13 } 14 } 15 struct point { 16 int x,y,z; 17 bool operator <(const point& q)const 18 { 19 return z<q.z; 20 } 21 }; 22 point yj[100001]; 23 struct node { 24 int w,id; 25 bool operator <(const node &q)const 26 { 27 return w<q.w; 28 } 29 }; 30 node yjj[20001]; 31 int _find(int x) 32 { 33 if (father[x]==x)return x; 34 father[x]=_find(father[x]); 35 return father[x]; 36 } 37 int main() 38 { 39 int t,n,m,q,i; 40 while (~scanf("%d",&t)) 41 { 42 while (t--) 43 { 44 scanf("%d %d %d",&n,&m,&q); 45 memset(a,0,sizeof(a)); 46 for (i=1;i<=m;i++) 47 scanf("%d %d %d",&yj[i].x,&yj[i].y,&yj[i].z); 48 sort(yj+1,yj+m+1); 49 lsy(n); 50 for (i=1;i<=q;i++) 51 { 52 scanf("%d",&yjj[i].w); 53 yjj[i].id=i; 54 } 55 sort(yjj+1,yjj+q+1); 56 int ans=0,j=1; 57 for (i =1;i<=q;i++) 58 { 59 while (j<=m&&yj[j].z<=yjj[i].w ) 60 { 61 int sx=_find(yj[j].x); 62 int sy=_find(yj[j].y); 63 j++; 64 if (sx==sy) continue; 65 ans+=(num[sx]+num[sy])*(num[sx]+num[sy]-1)-num[sx]*(num[sx]-1) - num[sy]*(num[sy]-1);//合并之后的关系 66 father[sx]=sy; 67 num[sy]+=num[sx]; 68 } 69 a[yjj[i].id]=ans; 70 } 71 for (i=1;i<=q;i++) 72 printf("%d\n",a[i]); 73 } 74 } 75 return 0; 76 }