模板题目了,又一个Krustral变形。。。
题意:给你P个点,目前有S个卫星频道(satellite channels),求一条边在连接后中的图中是最大的,但是要求是所用方案中最小的,明显的最小生成树。求最小生成树中最长的那条边就可以了,但是那些最长的边可以卫星通讯(Any two outposts with a satellite channel can communicate via the satellite,其实这里还是有一个疑问的:要是a,b用卫星频道,c,d也用卫星频道,那么如果这两段不用radio是不是也可以通讯啊,根据题意应该是不可以的,如果可以就A不了了),所以求第P-S条最小生成树的边长度。
代码如下:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 6 struct point 7 { 8 int x,y; 9 }p[1000]; 10 11 struct distance 12 { 13 int u,v; 14 double w; 15 }s[1000000]; 16 17 int S,P; 18 int num; 19 int f[1000]; 20 21 bool cmp(const distance& a,const distance& b) 22 { 23 if(a.w == b.w) 24 return a.u < b.u; 25 return a.w < b.w; 26 } 27 28 double dis(point a,point b) 29 { 30 return sqrt(1.0 * (a.x - b.x) * (a.x - b.x) + 1.0 * (a.y - b.y) * (a.y - b.y)); 31 } 32 33 int find(int x) 34 { 35 if(x == f[x]) 36 return x; 37 f[x] = find(f[x]); 38 return f[x]; 39 } 40 41 void init() 42 { 43 num = 0; 44 scanf("%d%d",&S,&P); 45 for(int i = 0;i < P;i ++) 46 { 47 scanf("%d%d",&p[i].x,&p[i].y); 48 for(int j = 0;j < i;j ++) 49 { 50 s[num].u = i; 51 s[num].v = j; 52 s[num ++].w = dis(p[i],p[j]); 53 } 54 } 55 56 for(int i = 0;i <= P;i ++) 57 { 58 f[i] = i; 59 } 60 std::sort(s,s + num,cmp); 61 } 62 63 void Krustral() 64 { 65 int k = 0; 66 for(int i = 0;i < num;i ++) 67 { 68 int fa = find(s[i].u); 69 int fb = find(s[i].v); 70 if(fa != fb) 71 { 72 f[fa] = fb; 73 k ++; 74 } 75 if(k == P - S) 76 { 77 printf("%.2lf\n",s[i].w); 78 return; 79 } 80 } 81 } 82 83 int main() 84 { 85 int cas; 86 scanf("%d",&cas); 87 while(cas --) 88 { 89 init(); 90 Krustral(); 91 } 92 93 return 0; 94 }