Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 13236 | Accepted: 4295 |
Description
Input
Output
Sample Input
1 2 4 0 100 0 300 0 600 150 750
Sample Output
212.13
题意:
给出所有的位置的坐标,,有两种通信方式,用卫星的话,无视距离,但是卫星的数量有限,另外就是直接传送消息,现给出所有的坐标和卫星的数量,让你求出,满足修建道路最短的情况下,需要修建的最长的道路长度...就这样理解吧...
题解:
按这个思路,也就是求最小生成树,但是需要求出的是最小生成树的第s+1大的边的长度.....
只要理解了题意,这个题就不难,下面完全就是克鲁斯卡尔算法的模板,不过注意处理方式...
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> using namespace std; int per[505],n,s,a[505],b[505]; struct lu { int a,b; double len; }x[250005]; double dis(int i,int j) { return sqrt((a[i]-a[j])*(a[i]-a[j])*1.0+(b[i]-b[j])*(b[i]-b[j])); } void init() { for(int i=1;i<=n;++i) { per[i]=i; } } bool cmp(lu a,lu b) { return a.len<b.len; } int find(int x) { int r=x; while(r!=per[r]) { r=per[r]; } int i=x,j; while(i!=r) { j=per[i];per[i]=r;i=j; } return r; } int join(int x,int y) { int fx=find(x),fy=find(y); if(fx!=fy) { per[fy]=fx; return 1; } return 0; } void kruskal() { int cnt=0;double maxn=0; for(int i=0;cnt<n;++i) { if(join(x[i].a,x[i].b)) { ++cnt;//累加生成树的边数 if(cnt==n-s)//找到需要的那条边之后 { maxn=x[i].len; break; } } } printf("%.2lf\n",maxn);//对应输出 } int main() { int t,i,j; scanf("%d",&t); while(t--) { scanf("%d%d",&s,&n); init(); for(i=0;i<n;++i) { scanf("%d%d",a+i,b+i); } int c=0; for(i=0;i<n-1;++i) { for(j=i+1;j<n;++j) { x[c].a=i+1;x[c].b=j+1; x[c].len=dis(i,j); ++c; } } sort(x,x+c,cmp); kruskal(); } return 0; }