Outlets HDU - 4463(最小生成树4)

拉斯维加斯的奥特莱斯无法满足游客 (尤其是来自中国的游客) 的购物需求。因此,将在沙漠中建造一座新的奥特莱斯,其中将包含很多商店。所有的商店之间以道路连接。设计者希望道路的总长度能够最小化。奥特莱斯的投资人雇佣了一名数据挖掘专家,该专家告诉他,Nike 商店和 Apple 商店必须由道路直接相连。请帮助他找出在此条件下的道路最短总长度。商店可被视作点,道路就是连接两个商店之间的线段。

输入

有多组测试数据。

对于每组测试数据,第一行仅包含一个整数 N (3 <= N <= 50),表示商店的数目。商店的编号从 1 到 N 。第二行包含了两个整数 p, q,表示第 p 家商店是一家 Nike 商店,第 q 家商店是一家 Apple 商店。接下来的 N 行中,第 i 行描述了第 i 家商店的位置。商店的位置被表示为两个整数 x, y (-100 <= x, y <= 100),即商店的位置坐标是 (x, y)。这 N 家商店均位于不同的位置。

输入以 N=0 结束。

输出

每组测试数据,对应输出道路总长度的最小值。结果应舍入到小数点后 2 位数。

示例输入

4
2 3
0 0
1 0
0 -1
1 -1
0

示例输出

3.41

这道题目有些意思,输入是一个个点的坐标,我们需要将一个一个点之间距离算出来,装进邻接矩阵。(操作简单)。然后就是怎么处理NIKE 和apple 点是直接相连的,我们可以直接先将这两个点连起来(将距离数组填充),从这两个点开始寻找权值最小的点,就是先将这两个点加进集合中(数组标记),一般的套路就是从第一个点开始寻找权值最小的点,这个就是有点特殊,其他的操作就是跟模板一样.

代码:

#include<iostream>
#include<string.h>
#include<string>
#include<bits/stdc++.h>
using namespace std;
const int inf=(1<<21);
const int maxn=55;
double maap[maxn][maxn];
double d[maxn];
int vis[maxn];

typedef struct 
{
	double x;
	double y;
	 
}point;
point dian[maxn];

int main()
{
	int i,j;
	int n;
	int p,q;
	while(cin>>n)
	{
		memset(vis,0,sizeof(vis));
		if(n==0)
			break;
		cin>>p>>q;
		vis[p]=1;
		vis[q]=1;
		for(i=1;i<=n;i++)
			{
				cin>>dian[i].x>>dian[i].y;
			}
		for(i=1;i<=n;i++)
			for(j=i;j<=n;j++)
			{
				if(i==j)
					maap[i][j]=0;
				else
				{
					double juli=sqrt((dian[i].x-dian[j].x)*(dian[i].x-dian[j].x)+(dian[i].y-dian[j].y)*(dian[i].y-dian[j].y));
					maap[i][j]=juli;
					maap[j][i]=juli;
				}
			}
	
	
	
			
		for(i=1;i<=n;i++)
			d[i]=maap[p][i];
		for(i=1;i<=n;i++)
			d[i]=min(d[i],maap[q][i]);
		
		
			
		double res=0;
		res+=maap[p][q];
	
	
		int pos;
		for(i=1;i<n;i++)
		{
			double minv=inf*1.0;
			for(j=1;j<=n;j++)
				if(!vis[j]&&minv>d[j])
				{
					pos=j;
					minv=d[j];
				}
			if(minv!=inf*1.0)
			{
			
				res+=minv;
				vis[pos]=1;
				for(j=1;j<=n;j++)
				{
					if(!vis[j]&&d[j]>maap[pos][j])
						d[j]=maap[pos][j];
				}
			}
			
			
		}
		
		printf("%.2lf\n",res);
	}
	
	
	
	
	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值