洛谷P1265 公路修建题解
题目描述
某国有n个城市,它们互相之间没有公路相通,因此交通十分不便。为解决这一“行路难”的问题,政府决定修建公路。修建公路的任务由各城市共同完成。
修建工程分若干轮完成。在每一轮中,每个城市选择一个与它最近的城市,申请修建通往该城市的公路。政府负责审批这些申请以决定是否同意修建。
政府审批的规则如下:
(1)如果两个或以上城市申请修建同一条公路,则让它们共同修建;
(2)如果三个或以上的城市申请修建的公路成环。如下图,A申请修建公路AB,B申请修建公路BC,C申请修建公路CA。则政府将否决其中最短的一条公路的修建申请;

(3)其他情况的申请一律同意。
一轮修建结束后,可能会有若干城市可以通过公路直接或间接相连。这些可以互相:连通的城市即组成“城市联盟”。在下一轮修建中,每个“城市联盟”将被看作一个城市,发挥一个城市的作用。
当所有城市被组合成一个“城市联盟”时,修建工程也就完成了。
你的任务是根据城市的分布和前面讲到的规则,计算出将要修建的公路总长度。
输入格式
第一行一个整数n,表示城市的数量。(n≤5000)
以下n行,每行两个整数x和y,表示一个城市的坐标。(-1000000≤x,y≤1000000)
输出格式
一个实数,四舍五入保留两位小数,表示公路总长。(保证有惟一解)
输入输出样例
4
0 0
1 2
-1 2
0 4
6.47
说明/提示
修建的公路如图所示:

解析:
MST裸题(不接受挨打)
由于是稠密图,所以采用了Prim算法
(稀疏图最好用克鲁斯卡尔)
对任意两个点都求出距离
然后对其跑一遍最小生成树
但是注意n的范围是5000,而大小限制为125MB
题目本身不难,但是会一直MLE,所以需要优化
我这里有三个代码,不同的分数
第一个是裸的开 5000*5000 double数组的Prim算法可以跑出80分的好成绩(不开O2)。、
第二个是裸的克鲁斯卡尔算法,不开O2估计70分,开了O2稳定80分,运气好的话就是90分
第三个就是Prim,与第一个Prim不同的是会减少大量的冗余运算,具体体现就是把 5000 * 5000 的数组取消掉
只会在需要计算的时候才会计算,将大大减少时间和内存,,,所以就AC了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<vector>
#define LL long long
#define re register
#define INF 0x7fffffff
#define Max 5002
#define D double
inline int read()
{
int s=,f=-;char ch=getchar();
while(ch<''||ch>'') {if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<='') s=s*+ch-'',ch=getchar();
return s*f;
}
int n;D ans=0.0,g[Max][Max],dis[Max];
bool vis[Max]={};
struct edge {
D x,y;
}t[Max];
D Dis(D x1,D y1,D x2,D y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main()
{
scanf("%d",&n);
for(re int i = ; i <= n ; ++ i) g[i][i]=,scanf("%lf%lf",&t[i].x,&t[i].y);
for(re int i = ; i <= n ; ++ i)
for(re int j = i+ ; j <= n ; ++ j)
g[i][j]=g[j][i]=Dis(t[i].x,t[i].y,t[j].x,t[j].y);
int pos;vis[]=;
for(re int i = ; i <= n ; ++ i) dis[i]=g[][i];
for(re int i = ; i < n ; ++ i) {
pos=;
for(re int j = ; j <= n ; ++ j) {
if(vis[j]==) continue;
if(!pos || dis[j] < dis[pos]) pos=j;
}
vis[pos]=;
ans+=dis[pos];
for(re int j = ; j <= n ; ++ j) {
if(vis[j]==) continue;
dis[j]=std::min(dis[j],g[pos][j]);
}
}
printf("%.2lf",ans);
return ;
}
80分裸的Prim
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<vector>
#define LL long long
#define re register
#define Max 5000*5000/2
#define D double
inline int read()
{
int s=,f=-;char ch=getchar();
while(ch<''||ch>'') {if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<='') s=s*+ch-'',ch=getchar();
return s*f;
}
int n,pa[Max];D ans=;
struct edge {
D x,y;
}t[Max];
struct DIS {
D dis;
int from,to;
friend bool operator<(DIS a,DIS b) {
return a.dis<b.dis;
}
}e[Max];
int find(int x)
{
if(x!=pa[x]) pa[x]=find(pa[x]);
return pa[x];
}
void join(int x,int y)
{
x=find(x);y=find(y);
pa[y]=x;
}
D Dis(D x1,D y1,D x2,D y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main()
{
scanf("%d",&n);int cnt=;
for(re int i = ; i <= n ; ++ i) pa[i]=i,scanf("%lf%lf",&t[i].x,&t[i].y);
for(re int i = ; i <= n ; ++ i)
for(re int j = i+ ; j <= n ; ++ j)
e[++cnt].dis=Dis(t[i].x,t[i].y,t[j].x,t[j].y),e[cnt].from=i,e[cnt].to=j;
int k=;
std::sort(e+,e++cnt);
for(re int i = ; i <= cnt ; ++ i) {
int x=e[i].from,y=e[i].to;D t=e[i].dis;
if(find(x)!=find(y)) join(x,y),ans+=t;
if(k==n-) break;
}
printf("%.2lf",ans);
return ;
}
开O2或许是90分或许是80分,看你是否脸黑
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<vector>
#define LL long long
#define re register
#define INF 0x7fffffff
#define Max 5002
#define D double
inline int read()
{
int s=,f=-;char ch=getchar();
while(ch<''||ch>'') {if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<='') s=s*+ch-'',ch=getchar();
return s*f;
}
int n;D ans=0.0,dis[Max];
bool vis[Max]={};
struct edge {D x,y;}t[Max];
D Dis(D x1,D y1,D x2,D y2){return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}
int main()
{
scanf("%d",&n);
for(re int i = ; i <= n ; ++ i) dis[i]=INF,scanf("%lf%lf",&t[i].x,&t[i].y);
int pos;dis[]=;
for(re int i = ; i <= n ; ++ i) {
D m=INF*1.0;
for(re int j = ; j <= n ; ++ j)
if(dis[j] < m && !vis[j]) m=dis[j],pos=j;
vis[pos]=;
ans+=m;
for(re int j = ; j <= n ; ++ j) {
if(vis[j]==) continue;
D d=Dis(t[pos].x,t[pos].y,t[j].x,t[j].y);
dis[j]=std::min(dis[j],d);
}
}
printf("%.2lf",ans);
return ;
}
AC 代码
洛谷P1265 公路修建题解的更多相关文章
- 洛谷P1265 公路修建(Prim)
To 洛谷.1265 公路修建 题目描述 某国有n个城市,它们互相之间没有公路相通,因此交通十分不便.为解决这一“行路难”的问题,政府决定修建公路.修建公路的任务由各城市共同完成. 修建工程分若干轮完 ...
- 洛谷P1265 公路修建
P1265 公路修建 177通过 600提交 题目提供者该用户不存在 标签图论 难度普及+/提高 提交该题 讨论 题解 记录 最新讨论 long long类型赋值-1为什么… p党80的进 为什么不过 ...
- 洛谷——P1265 公路修建
P1265 公路修建 题目描述 某国有n个城市,它们互相之间没有公路相通,因此交通十分不便.为解决这一“行路难”的问题,政府决定修建公路.修建公路的任务由各城市共同完成. 修建工程分若干轮完成.在每一 ...
- 洛谷P1265 公路修建——prim
给一手链接 https://www.luogu.com.cn/problem/P1265 这道题本质上就是最小生成树,题目描述就是prim的思想 TIP:注意稠密图和稀疏图的区别 #include&l ...
- 洛谷 [P1265] 公路修建
本题的描述:城市联盟,最短距离.. 使人想到了prim求MST,再一看数据范围:完全图!,那么一定得用prim,因为只有5000个点,所以不加优化的prim就能过. #include <iost ...
- 洛谷P2832 行路难 分析+题解代码【玄学最短路】
洛谷P2832 行路难 分析+题解代码[玄学最短路] 题目背景: 小X来到了山区,领略山林之乐.在他乐以忘忧之时,他突然发现,开学迫在眉睫 题目描述: 山区有n座山.山之间有m条羊肠小道,每条连接两座 ...
- 【洛谷P3960】列队题解
[洛谷P3960]列队题解 题目链接 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有 n×m ...
- 洛谷P2242 公路维修问题
To 洛谷.2242 公路维修问题 题目描述 由于长期没有得到维修,A国的高速公路上出现了N个坑.为了尽快填补好这N个坑,A国决定对M处地段采取交通管制.为了求解方便,假设A国的高速公路只有一条,而且 ...
- 洛谷P2312 解方程题解
洛谷P2312 解方程题解 题目描述 已知多项式方程: \[a_0+a_1x+a_2x^2+\cdots+a_nx^n=0\] 求这个方程在 \([1,m]\) 内的整数解(\(n\) 和 \(m\) ...
随机推荐
- sql特殊日期
--a. 本月的第一天 select dateadd(mm, datediff(mm,0,getdate()), 0) as 本月的第一天 --b. 本月的最后一天 select dateadd(ms ...
- 女性对DeepNude脱衣技术的防护
写在前面的话 本文不提供下载方式,开源部分只是社区逆向后公开的部分源码 这篇文章有些人看了可能会比较极端,但不从技术角度分析又谈何防护?攻与防一直存在,不管是安全还是AI都是一样 你极端不极端,它就在 ...
- 将windows共享文件夹挂载到Linux
今天想用docker部署下 .net core的 服务,需要把代码文件从windows传到linux,以前一直都是拖拽的,这次安装的系统没有图形界面, 所以到网上找到了下面的这种方法,将共享文件夹挂载 ...
- 1+X证书学习日志——css 2D&过渡
css 位移常用属性 transform:translate(x,y): transform:translateX(); transform:translateY(); 旋转属性 2d旋转: tran ...
- Android为TV端助力之热修复原理
通过源码我们知道Android加载类是通过ClassLoad类里面的findClass先去查找的,如下图所示 通过看源码我们知道,ClassLoad是一个抽象类,它本身并没有实现findclass() ...
- Tomcat启动堆栈异常
近日部署项目到Tomcat,访问一直404. 于是查看 catalina.out 日志信息,发现如下信息 30-Jun-2019 16:38:03.642 SEVERE [main] org.apac ...
- 二十六、聊聊mysql如何实现分布式锁
分布式锁的功能 分布式锁使用者位于不同的机器中,锁获取成功之后,才可以对共享资源进行操作 锁具有重入的功能:即一个使用者可以多次获取某个锁 获取锁有超时的功能:即在指定的时间内去尝试获取锁,超过了超时 ...
- eclipse svn 提交、更新报错
问题描述: svn: Unable to connect to a repository at URL 'https://test.com/svn/clouds/trunk/fire_Alarm'sv ...
- css3卡片阴影效果
1.css3阴影用到的知识点:阴影box-shadow和插入:after before HTML部分: <!DOCTYPE html> <html> <head> ...
- X509IncludeOption 枚举
X509IncludeOption 枚举 指定 X.509 数据应包括 X.509 证书链的哪些内容. EndCertOnly 2 X.509 链信息中仅包括最终证书. ExcludeRoot 1 包 ...