#2020.02.05训练题解#最小生成树入门(D题)

题源HDU-4463

HDU-4463-Outlets

Description
In China, foreign brand commodities are often much more expensive than abroad. The main reason is that we Chinese people tend to think foreign things are better and we are willing to pay much for them. The typical example is, on the United Airline flight, they give you Haagendazs ice cream for free, but in China, you will pay $10 to buy just a little cup.
So when we Chinese go abroad, one of our most favorite activities is shopping in outlets. Some people buy tens of famous brand shoes and bags one time. In Las Vegas, the existing outlets can’t match the demand of Chinese. So they want to build a new outlets in the desert. The new outlets consists of many stores. All stores are connected by roads. They want to minimize the total road length. The owner of the outlets just hired a data mining expert, and the expert told him that Nike store and Apple store must be directly connected by a road. Now please help him figure out how to minimize the total road length under this condition. A store can be considered as a point and a road is a line segment connecting two stores.

Input
There are several test cases. For each test case: The first line is an integer N( 3 <= N <= 50) , meaning there are N stores in the outlets. These N stores are numbered from 1 to N. The second line contains two integers p and q, indicating that the No. p store is a Nike store and the No. q store is an Apple store. Then N lines follow. The i-th line describes the position of the i-th store. The store position is represented by two integers x,y( -100<= x,y <= 100) , meaning that the coordinate of the store is (x,y). These N stores are all located at different place. The input ends by N = 0.

Output
For each test case, print the minimum total road length. The result should be rounded to 2 digits after decimal point.

Sample Input
4
2 3
0 0
1 0
0 -1
1 -1
0

Sample Output
3.41

题意

  • 多组数据,每组数据先输入一个N,代表有N个商店,N为零时程序结束
  • 然后再输入一个p和一个q,代表第p家和第q家商店之间必须有道路连通
  • 接下来输入N行,代表1-N个商店的坐标
  • 每组数据输出让该组所有商店连通,最少共需修的道路长度

题解

  • 这是最小生成树模板题,分别输入对应量,调用函数即可
  • 此题除了输入的是点坐标,需要新建数组保存点距离(权值)外,还指定两个商店之间必须连通
  • 那么保存权值时,可以在数组第一个位置保存p和q之间的距离(权值),其他遍历保存,再遇到p和q之间就跳过
  • 保存完毕后,Kruskal算法需要权值升序,此题需要关注升序范围
  • 为了不连通出环最优先连通的就是指定的p和q商店,那么需要升序的是**第二个到末尾*
  • 注意输出的是道路长度,即距离,是一个实数,且要求保留3位输出

涉及知识点

  • 最小生成树MST 算法(此题用到Kruskal算法)
  • 对于最小生成树的算法-详见链接博客介绍最小生成树

AC代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define dis 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))
const int maxn=1e4+10;
int father[maxn];
int T,n,cnt,key,p,q;
double sum;
struct node
{
	int x;
	int y;
	double w;
}dian[maxn],edge[maxn];
bool cmp(node a,node b)
{
	return a.w<b.w;
}
int find(int m)
{
	return m==father[m]?m:father[m]=find(father[m]);
}
void kruskal()
{
	sum=0.0,cnt=0; 
	for(int i=1;i<=key;++i)
	{
		int fx=find(edge[i].x);
		int fy=find(edge[i].y);
		if(fx==fy) continue;//判断其是否在同一个连通分量
		sum+=edge[i].w;
		father[fx]=fy;
		cnt++;//统计有多少条边,每合并一次就是多一条边,最小生成树n-1条边 
		if(cnt==n-1) return;
	}
}
int main()
{
	while(~scanf("%d",&n)&&n)
	{
		for(int i=1;i<=n;++i) father[i]=i;
		scanf("%d %d",&p,&q);
		for(int i=1;i<=n;++i) scanf("%d %d",&dian[i].x,&dian[i].y);
		key=1;
		edge[1].x=p;
		edge[1].y=q;
		edge[1].w=sqrt((dian[p].x-dian[q].x)*(dian[p].x-dian[q].x)+(dian[p].y-dian[q].y)*(dian[p].y-dian[q].y));
		for(int i=1;i<=n;++i)
		{
			for(int j=1;j<i;++j)//j永远比i小 
			{
				if((i==p&&j==q)||(i==q&&j==p)) continue;
				key++;
				edge[key].x=i;
				edge[key].y=j;
				edge[key].w=dis;
			}
		}
		sort(edge+2,edge+key+1,cmp);//对边按照权值进行排序
		kruskal();
		printf("%.2f\n",sum);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值