hrbust 哈理工oj 网线【MST+Prim】

来源:互联网 发布:球球大作战小糖果软件 编辑:程序博客网 时间:2024/05/16 16:23

网线Time Limit: 5000 MSMemory Limit: 32768 KTotal Submit: 68(17 users)Total Accepted: 17(15 users)Rating: Special Judge: NoDescription

   试设计一个网络连接某个区域中的一些地点。给定这些地点所在的位置,网线的长度就是两个地点的线段距离,假定,给定的网线可以直接或间接的连接该地区中的所有点,试为这个地区设计一个网络系统,使得该地区所有地点都可以直接或间接的连接,并且使用网线长度最短。

Input

输入一个数字n(n<1000),给出这n个点的位置(x,y),即坐标(0≤x<1000,0≤y<1000)。

Output输出网线的最短距离,保留小数点后四位。Sample Input

1

1 1

2

0 0

1 1

3

0 0

0 1

1 1

Sample Output

0.0000

1.4142

2.0000

Author彭文文@hrbust

N的数据范围比较大,克鲁斯卡算法会超时,即使路径压缩了,即使使用快排了,还是会超时,所以被逼无奈,只能用prim来做。

在计算过程中呢,我们需要考虑一个精度问题,我们如果在入图的时候就使用double或者float来写的话,很容易产生精度差,当然就会有wa的可能。

所以我们在计算过程中,入图的时候用int,只有在生成树的过程中加上sqrt(map【i】【j】)就行了,这个时候我们避免了精度差问题,也省略了很多不必要的*1.0之类的步骤。

AC代码:

#include <stdio.h>#include <string.h>#include <math.h>#include <algorithm>using namespace std;#define inf 0x6ffffffstruct zuobiao{    int x,y;}a[1004];int vis[1005];//用来表示这个点有没有遍历的到.int  dis[1005];int  map[1005][1005];int n;double sum;int diss(zuobiao a,zuobiao b){    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}void prim(){int i,j,k,min;for(i=2;i<=n;i++)dis[i]=map[1][i];vis[1]=1;for(i=2;i<=n;i++)//经过N次遍历一定能遍历所有的点 也就是完成了最终目标.{min=inf;for(j=1;j<=n;j++){if(vis[j]==0 &&dis[j]<min){min=dis[j];k=j;}}if(min==inf)break;vis[k]=1;sum+=sqrt(1.0*min);//完成了一次权值加和.for(j=2;j<=n;j++){if(vis[j]==0 &&dis[j]>map[k][j])dis[j]=map[k][j];}//更新最优解.}}int main(){    while(~scanf("%d",&n))    {        memset(vis,0,sizeof(vis));        memset(dis,0,sizeof(dis));        for(int i=1;i<=n;i++)        {            for(int j=1;j<=n;j++)            {                map[i][j]=inf*1.0;            }        }        for(int i=1;i<=n;i++)        {            scanf("%d%d",&a[i].x,&a[i].y);            for(int j=1;j<i;j++)            {                map[i][j]=map[j][i]=diss(a[i],a[j]);            }        }        sum=0;        prim();        printf("%.4lf\n",sum);    }}









1 0
原创粉丝点击