洛谷P1265 公路修建——最小生成树,prim算法,不存图,边算边求MST

本文详细解析了使用Prim算法解决最小生成树问题的方法,针对完全图且顶点数不超过5000的情况,避免了Kruskal算法的内存溢出问题。文章通过实例讲解了如何计算顶点间的距离,并提供了AC代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

分析:

本质是求最小生成树。对于规则2,构成环则申请时去掉最大边。

因为最多有5000个点,又是完全图,故不采用Kruskal算法。

用Prim算法时,用邻接矩阵则会MLE。只有涉及到松驰点的权值时,再计算边长。

易错点:

计算两点间距离时,因为点的坐标是整数,因此要将坐标平方进行类型强制转换。

double value(int i,int j){
	return sqrt( (double)(x[i]-x[j])*(x[i]-x[j]) + (double)(y[i]-y[j])*(y[i]-y[j]) );
}

也可以写成:

double value(int i,int j){
	return sqrt(1.0*(x[i]-x[j])*(x[i]-x[j]) + 1.0*(y[i]-y[j])*(y[i]-y[j]) );
}

注:

1.0*10,结果是double型的10;

但10*1.0,结果什么呢?

如果写成:

double value(int i,int j){
	return sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) );
}

则卡掉9个点。

AC代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int m,x[5001],y[5001];
int vis[5001];
double dis[5001],dist;
double ans=0;
double value(int i,int j){
	return sqrt( (double)(x[i]-x[j])*(x[i]-x[j]) + (double)(y[i]-y[j])*(y[i]-y[j]) );
}
void prim(){
	for(int i=1;i<=m;i++)dis[i]=1e20;
	dis[1]=0;
	int V=1;
	for(int i=1;i<=m;i++){
		double minn=1e20;
		for(int j=1;j<=m;j++)
			if(!vis[j])
				if(minn>dis[j]){
					minn=dis[j];
					V=j;
				}
		vis[V]=1;
		ans+=dis[V];
		for(int j=1;j<=m;j++)
			if(!vis[j]){
				dist=value(V,j);
				if(dis[j]>dist)dis[j]=dist;
			}
	}
}
int main(){
	cin>>m;
	for(int i=1;i<=m;i++)cin>>x[i]>>y[i];
	prim();
	printf("%.2f\n",ans);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值