交大OJ1231: 谁能上天堂

来源:互联网 发布:系统集成软件有哪些 编辑:程序博客网 时间:2024/04/29 15:49

题意: 从起点到终点,让这条路径上的每一条边都尽量短(不是求总路径最短)。

做法: 运用kruscal的做法,每次构造最短边,知道起点和终点在一个集合中,那么当前的最短边就是 所求结果!


代码:

#include<stdio.h>#include<algorithm>#include<cmath>using namespace std;int fa[100005],son[100005];struct Point{    double x,y;  //开始没注意坐标是 实数,错了几次}point[100005];struct Node{    int a,b;  //aµã£¬bµã    double v;}e[100005];double dis(int a,int b){    return sqrt( (point[a].x-point[b].x)*(point[a].x-point[b].x)+                 (point[a].y-point[b].y)*(point[a].y-point[b].y) );}bool cmp(struct Node aa,struct Node bb){    return aa.v<bb.v;}int find(int x){    return (x==fa[x]?x:find(fa[x]) );}int join(int x,int y){    x=find(x);    y=find(y);    if(x==y) return 0;    if(son[x]>son[y])    {        son[x]+=son[y];        fa[y]=x;    }else{        son[y]+=son[x];        fa[x]=y;    }    return 1;}int main(){  //  freopen("data.in","r",stdin);   // freopen("da1.out","w",stdout);    int i,j,n,len,num,ncase;    double ans;    ncase=0;    while(scanf("%d",&n))    {        if(n==0) break;        for(i=1;i<=n;i++)            scanf("%lf%lf",&point[i].x,&point[i].y);        num=0;        for(i=1;i<=n;i++)            for(j=i+1;j<=n;j++)                {                    num++;                    e[num].a=i;                    e[num].b=j;                    e[num].v=dis(i,j);                }        sort(e+1,e+num+1,cmp);        for(i=1;i<=n;i++)            fa[i]=i,son[i]=1;        len=0;        for(i=1;i<=num;i++)            if(join(e[i].a,e[i].b))            {                len++;               // printf("e%d=%.2f\n",i,e[i].v);                if(find(1)==find(2)) {ans=e[i].v; break; }  // 此处判断条件出错,不是要构造完全的生成树,只要起点、终点在一个集合中就行!            }        printf("case #%d : %.3lf\n\n",++ncase,ans);    }    return 0;}


原创粉丝点击