题目描述

某国有n个城市,它们互相之间没有公路相通,因此交通十分不便。为解决这一“行路难”的问题,政府决定修建公路。修建公路的任务由各城市共同完成。

修建工程分若干轮完成。在每一轮中,每个城市选择一个与它最近的城市,申请修建通往该城市的公路。政府负责审批这些申请以决定是否同意修建。

政府审批的规则如下:

(1)如果两个或以上城市申请修建同一条公路,则让它们共同修建;

(2)如果三个或以上的城市申请修建的公路成环。如下图,A申请修建公路AB,B申请修建公路BC,C申请修建公路CA。则政府将否决其中最短的一条公路的修建申请;

(3)其他情况的申请一律同意。

一轮修建结束后,可能会有若干城市可以通过公路直接或间接相连。这些可以互相:连通的城市即组成“城市联盟”。在下一轮修建中,每个“城市联盟”将被看作一个城市,发挥一个城市的作用。

当所有城市被组合成一个“城市联盟”时,修建工程也就完成了。

你的任务是根据城市的分布和前面讲到的规则,计算出将要修建的公路总长度。

输入格式

第一行一个整数n,表示城市的数量。(n≤5000)

以下n行,每行两个整数x和y,表示一个城市的坐标。(-1000000≤x,y≤1000000)

输出格式

一个实数,四舍五入保留两位小数,表示公路总长。(保证有惟一解)

输入输出样例

输入 #1复制

4
0 0
1 2
-1 2
0 4

输出 #1复制

6.47

说明/提示

修建的公路如图所示:

解析:

MST裸题(不接受挨打)

由于是稠密图,所以采用了Prim算法
(稀疏图最好用克鲁斯卡尔)
对任意两个点都求出距离
然后对其跑一遍最小生成树
但是注意n的范围是5000,而大小限制为125MB

题目本身不难,但是会一直MLE,所以需要优化

我这里有三个代码,不同的分数

第一个是裸的开 5000*5000 double数组的Prim算法可以跑出80分的好成绩(不开O2)。、

第二个是裸的克鲁斯卡尔算法,不开O2估计70分,开了O2稳定80分,运气好的话就是90分

第三个就是Prim,与第一个Prim不同的是会减少大量的冗余运算,具体体现就是把 5000 * 5000 的数组取消掉

只会在需要计算的时候才会计算,将大大减少时间和内存,,,所以就AC了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<string>
 6 #include<algorithm>
 7 #include<iomanip>
 8 #include<cstdlib>
 9 #include<queue>
10 #include<set>
11 #include<map>
12 #include<stack>
13 #include<vector>
14 #define LL long long
15 #define re register
16 #define INF 0x7fffffff
17 #define Max 5002
18 #define D double
19 inline int read()
20 {
21     int s=0,f=-1;char ch=getchar();
22     while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
23     while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
24     return s*f;
25 }
26 int n;D ans=0.0,g[Max][Max],dis[Max];
27 bool vis[Max]={0};
28 struct edge {
29     D x,y;
30 }t[Max];
31 D Dis(D x1,D y1,D x2,D y2)
32 {
33     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
34 }
35 int main()
36 {
37     scanf("%d",&n);
38     for(re int i = 1 ; i <= n ; ++ i) g[i][i]=0,scanf("%lf%lf",&t[i].x,&t[i].y);
39     for(re int i = 1 ; i <= n ; ++ i)
40         for(re int j = i+1 ; j <= n ; ++ j)
41             g[i][j]=g[j][i]=Dis(t[i].x,t[i].y,t[j].x,t[j].y);
42     int pos;vis[1]=1;
43     for(re int i = 1 ; i <= n ; ++ i) dis[i]=g[1][i];
44     for(re int i = 1 ; i < n ; ++ i) {
45         pos=0;
46         for(re int j = 1 ; j <= n ; ++ j) {
47             if(vis[j]==1) continue;
48             if(!pos || dis[j] < dis[pos]) pos=j;
49         }
50         vis[pos]=1;
51         ans+=dis[pos];
52         for(re int j = 1 ; j <= n ; ++ j) {
53             if(vis[j]==1) continue;
54             dis[j]=std::min(dis[j],g[pos][j]);
55         }
56     }
57     printf("%.2lf",ans);
58     return 0;
59 }

80分裸的Prim

 1 // luogu-judger-enable-o2
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<string>
 7 #include<algorithm>
 8 #include<iomanip>
 9 #include<cstdlib>
10 #include<queue>
11 #include<set>
12 #include<map>
13 #include<stack>
14 #include<vector>
15 #define LL long long
16 #define re register
17 #define Max 5000*5000/2
18 #define D double
19 inline int read()
20 {
21     int s=0,f=-1;char ch=getchar();
22     while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
23     while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
24     return s*f;
25 }
26 int n,pa[Max];D ans=0;
27 struct edge {
28     D x,y;
29 }t[Max];
30 struct DIS {
31     D dis;
32     int from,to;
33     friend bool operator<(DIS a,DIS b) {
34         return a.dis<b.dis;
35     }
36 }e[Max];
37 int find(int x)
38 {
39     if(x!=pa[x]) pa[x]=find(pa[x]);
40     return pa[x];
41 }
42 void join(int x,int y)
43 {
44     x=find(x);y=find(y);
45     pa[y]=x;
46 }
47 D Dis(D x1,D y1,D x2,D y2)
48 {
49     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
50 }
51 int main()
52 {
53     scanf("%d",&n);int cnt=0;
54     for(re int i = 1 ; i <= n ; ++ i) pa[i]=i,scanf("%lf%lf",&t[i].x,&t[i].y);
55     for(re int i = 1 ; i <= n ; ++ i)
56         for(re int j = i+1 ; j <= n ; ++ j)
57             e[++cnt].dis=Dis(t[i].x,t[i].y,t[j].x,t[j].y),e[cnt].from=i,e[cnt].to=j;
58     int k=0;
59     std::sort(e+1,e+1+cnt);
60     for(re int i = 1 ; i <= cnt ; ++ i) {
61         int x=e[i].from,y=e[i].to;D t=e[i].dis;
62         if(find(x)!=find(y)) join(x,y),ans+=t;
63         if(k==n-1) break;
64     }
65     printf("%.2lf",ans);
66     return 0;
67 }

开O2或许是90分或许是80分,看你是否脸黑

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<string>
 6 #include<algorithm>
 7 #include<iomanip>
 8 #include<cstdlib>
 9 #include<queue>
10 #include<set>
11 #include<map>
12 #include<stack>
13 #include<vector>
14 #define LL long long
15 #define re register
16 #define INF 0x7fffffff
17 #define Max 5002
18 #define D double
19 inline int read()
20 {
21     int s=0,f=-1;char ch=getchar();
22     while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
23     while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
24     return s*f;
25 }
26 int n;D ans=0.0,dis[Max];
27 bool vis[Max]={0};
28 struct edge {D x,y;}t[Max];
29 D Dis(D x1,D y1,D x2,D y2){return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}
30 int main()
31 {
32     scanf("%d",&n);
33     for(re int i = 1 ; i <= n ; ++ i) dis[i]=INF,scanf("%lf%lf",&t[i].x,&t[i].y);
34     int pos;dis[1]=0;
35     for(re int i = 1 ; i <= n ; ++ i) {
36         D m=INF*1.0;
37         for(re int j = 1 ; j <= n ; ++ j)
38             if(dis[j] < m && !vis[j]) m=dis[j],pos=j;
39         vis[pos]=1;
40         ans+=m;
41         for(re int j = 1 ; j <= n ; ++ j) {
42             if(vis[j]==1) continue;
43             D d=Dis(t[pos].x,t[pos].y,t[j].x,t[j].y);
44             dis[j]=std::min(dis[j],d);
45         }
46     }
47     printf("%.2lf",ans);
48     return 0;
49 }

AC 代码

转载于:https://www.cnblogs.com/handsomegodzilla/p/11291039.html

洛谷P1265 公路修建题解相关推荐

  1. 洛谷 P1265 公路修建 题解

    1 题面 公路修建 2 分析 这题特别的地方就是边多,5000×50005000\times 50005000×5000的边用kruscal空间不对. 主要空间瓶颈就是边的权是存不下来的,然而krus ...

  2. 洛谷P1265 公路修建

    题目描述 ---------- 太长不看版:给你一个数字n,接下来是n个点的x.y坐标,求个最小生成树 ---------- 某国有n个城市,它们互相之间没有公路相通,因此交通十分不便.为解决这一&q ...

  3. 洛谷 [P1265] 公路修建

    本题的描述:城市联盟,最短距离.. 使人想到了prim求MST,再一看数据范围:完全图!,那么一定得用prim,因为只有5000个点,所以不加优化的prim就能过. #include <iost ...

  4. 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)

    洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...

  5. 洛谷P2312 解方程题解

    洛谷P2312 解方程题解 题目描述 已知多项式方程: \[a_0+a_1x+a_2x^2+\cdots+a_nx^n=0\] 求这个方程在 \([1,m]\) 内的整数解(\(n\) 和 \(m\) ...

  6. 洛谷P1273 有线电视网 题解

    洛谷P1273 有线电视网 题解 题目链接:P1273 有线电视网 题意: 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为 ...

  7. 洛谷P4568 [JLOI2011] 飞行路线 题解

    洛谷P4568 [JLOI2011] 飞行路线 题解 题目链接:P4568 [JLOI2011] 飞行路线 题意: Alice 和 Bob 现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公 ...

  8. 洛谷P3426 [POI2005]SZA-Template 题解

    洛谷P3426 [POI2005]SZA-Template 题解 题目链接:P3426 [POI2005]SZA-Template 题意:你打算在纸上印一串字母. 为了完成这项工作,你决定刻一个印章. ...

  9. 洛谷P1156 垃圾陷阱 题解浅谈刷表法与填表法

    洛谷P1156 垃圾陷阱 题解&浅谈刷表法与填表法 填表法 :就是一般的动态规划,当前点的状态,可以直接用状态方程,根据之前点的状态推导出来. 刷表法:由当前点的状态,更新其他点的状态.需要注 ...

最新文章

  1. 系统学习机器学习之决策树
  2. EBS并发管理器启动失败,系统暂挂,在重置计数器之前修复管理程序
  3. Oracle 基础篇 --- 索引选项
  4. Java日期型集合排序
  5. JAVA接口继承、抽象类等
  6. csgo自动选择服务器,CSGO服务器怎么选择合适的配置?CSGO服务器如何选择系统?...
  7. 运动控制卡中伺服电机的规划位置与编码器位置的区别
  8. 物联网可靠连接——PLC-IOT电力线载波通讯
  9. 面试经验|传音控股自动化测试
  10. ngx_lua arg类型_使用模式,Arg和类型微调Drupal主题
  11. Qt for Python做一个虚拟示波器软件
  12. 新东方 词根词缀 excel_词根词缀记忆英语单词,高效,不易遗忘
  13. 国外访问学者申请政策解析
  14. 嵌入式系统学习-------1.什么是嵌入式系统?
  15. ARM + RISC-V双核锁步DCLS Lockstep技术总结
  16. Python爬虫入门-小试ImagesPipeline爬取pixabay和煎蛋之为什么是‘404’
  17. 【转载】风控-风控策略逻辑
  18. [Windows] - DNS防污染工具Pcap_DNSProxy
  19. 遍历指定目录下指定类型文件的函数(fatkun Fix版)
  20. Android二维码生成器工具类

热门文章

  1. 深入理解html5系列-文本标签
  2. Transact-SQL 示例 - 查询某个数据库内的所有表的记录行数及其总和
  3. [转载]常用正则表达式
  4. 107.网络服务质量包括哪些(QoS)
  5. 104.路由协议有哪些?
  6. 野火STM32F103教学视频完整目录(配合霸道-指南者开发板)
  7. python整理数据_Python常见数据结构整理
  8. matlab verilog 接口,使用SystemVerilog简化FPGA中的接口
  9. 012_日期内建函数
  10. 002_ZooKeeper安装配置