Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 30450 | Accepted: 9812 |
Description
Input
Output
Sample Input
2 0 0 3 4 3 17 4 19 4 18 5 0
Sample Output
Scenario #1 Frog Distance = 5.000 Scenario #2 Frog Distance = 1.414
题意:
说的是,两个青蛙分别在一个水池中的两个石头上,一个青蛙想去找另一只青蛙,但是她不想游泳(这还是青蛙吗),然后就借助别的石头跳啊跳,问他最远一次至少要要跳多远能让他到达目的地,第一个坐标是起点,第二个坐标是终点,其他的位置是别的石头坐标
题解:
贪心加最小生成树的题目,第一眼看到的时候,还以为是最短路,后来朋友说可以用并查集,然后介绍给我一种很好的方法,当时就感觉很巧妙,就试着做了,挺好的
用的是并查集的最小生成树的思想:在生成树的时候,每次都判断和更新起点和终点是否相连,如果相连,那么这条边就是所求的,因为这条边肯定是已加入集合里最长的距离,否则的话,就继续更新状态,就这样持续生成树,一直到起点和终点相连,就得到需要的数据了
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> using namespace std; int per[205],n,t=0; double a[205],b[205]; 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-1;++i) { if(join(x[i].a,x[i].b)) { if(find(1)==find(2))//这里很巧妙 { maxn=x[i].len;//找到就赋值 break;//跳出循环,加快速度 } ++cnt;//每次统计边数 } } printf("Scenario #%d\nFrog Distance = %.3f\n\n",++t,maxn);//注意输出格式 } int main() { int i,j; while(scanf("%d",&n),n) { init(); for(i=0;i<n;++i) { scanf("%lf%lf",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; }