[Jzoj] 1244. 修建道路

题目描述

Farmer John最近得到了一些新的农场,他想新修一些道路使得他的所有农场可以经过原有的或是新修的道路互达(也就是说,从任一个农场都可以经过一些首尾相连道路到达剩下的所有农场)。有些农场之间原本就有道路相连。所有N(1 <= N <= 1,000)个农场(用1…N顺次编号)在地图上都表示为坐标为(X_i, Y_i)的点(0 <= X_i <= 1,000,000;0 <= Y_i <= 1,000,000),两个农场间道路的长度自然就是代表它们的点之间的距离。现在Farmer John也告诉了你农场间原有的M(1 <= M <= 1,000)条路分别连接了哪两个农场,他希望你计算一下,为了使得所有农场连通,他所需建造道路的最小总长是多少。

题目解析

先计算出点之间的距离,构造成邻接矩阵,对于已有的道路将距离变为0

求最小生成树即可。因为是稠密图,用 P r i m Prim Prim会比较好。

代码

#include<bits/stdc++.h>
#define N 1005
using namespace std;
int n,m;
int x[N],y[N]; 
bool vis[N];
double mat[N][N],dis[N],ans;
void prim()
{
	for(int i=1;i<=n;i++) dis[i]=1e9;
	dis[1]=0;
	for(int i=1,u;i<n;i++)
	{
	  u=0;
	  for(int j=1;j<=n;j++)
	   if(!vis[j]&&(u==0||dis[j]<dis[u])) u=j;
	  vis[u]=1;
	  for(int j=1;j<=n;j++)
	   if(!vis[j]) dis[j]=min(dis[j],mat[u][j]);
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=1000;i++) for(int j=1;j<=1000;j++) mat[i][j]=1e9;
	for(int i=1;i<=n;i++)
	{
	  scanf("%d%d",&x[i],&y[i]);
	  for(int j=1;j<i;j++)
	   mat[i][j]=mat[j][i]=sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(double)(y[i]-y[j])*(y[i]-y[j]));
	}
	for(int i=1,u,v;i<=m;i++)
	 scanf("%d%d",&u,&v),mat[u][v]=mat[v][u]=0;
	prim();
	for(int i=1;i<=n;i++) ans+=dis[i];
	printf("%.2lf",ans);
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值