首页 > 其他 > 详细

【洛谷习题】公路修建

时间:2018-09-02 22:12:46      阅读:293      评论:0      收藏:0      [点我收藏+]

本想着做完这道题,就暂时告别MST,但越到了这个时候,惊喜也就越多,呵呵。

题目链接:https://www.luogu.org/problemnew/show/P1265


 

哎,上去就mengbi第二个规则,自己试了好半天,始终举不出例子来,只好去看题解,,,真想吐血!原来第二种情况根本不存在,这道题其实也是要求最小生成树!

好,Kruskal上!砰!

n<=5000?那么边数最多可有25000000!显然内存方面就会炸。

再仔细一看题解,哦,是用Prim。记得曾经dalao和我说过,Prim并不是一无是处,他就用到过一次,当时没仔细听,没想到最终还是翻了船。

去啃Prim,发现确实Kruskal不能完全代替他。具体详见另一篇博客《Prim算法》。

边是不可以全部保存的,而Prim算法的过程刚好可以不用保存每条边,只需动态查询边的长度即可。Prim适用于稠密图,所以这道题非Prim莫属了。

高高兴兴写上Prim提交。。。什么!只有10分?找了好半天都不知道哪错了,摁着正解使劲读,最后才意识到求两点间距离时原来会溢出。

比如:sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)),万一坐标的范围很大,中间过程(像(x1-x2)*(x1-x2))就会溢出!

唔,可算是完了。

技术分享图片
 1 #include<cstdio>
 2 #include<cmath>
 3 const int maxn=5005;
 4 const double inf=1e9;
 5 int n,x[maxn],y[maxn],vis[maxn];
 6 double minw[maxn],ans=0;
 7 double dis(int i,int j) {
 8     return sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(double)(y[i]-y[j])*(y[i]-y[j]));
 9 } //一定要注意这里别溢出!!!
10 int main() {
11     scanf("%d",&n);
12     for(int i=1;i<=n;++i) scanf("%d%d",&x[i],&y[i]);
13     int index;
14     double mmin;
15     for(int i=2;i<=n;++i) minw[i]=inf;
16     for(int i=1;i<=n;++i) {
17         mmin=inf;
18         for(int j=1;j<=n;++j) if(!vis[j]&&minw[j]<mmin) index=j,mmin=minw[j];
19         vis[index]=1;
20         ans+=mmin;
21         for(int j=1;j<=n;++j) {
22             double d=dis(index,j);
23             if(!vis[j]&&d<minw[j]) minw[j]=d;
24         }
25     }
26     printf("%.2f",ans);
27     return 0;
28 }
AC代码

 

【洛谷习题】公路修建

原文:https://www.cnblogs.com/Mr94Kevin/p/9575468.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!