洛谷 P1783 海滩防御(最小生成树)

传送门


解题思路

和上一道题基本相同。
但是这个题题面是真的复杂,读了好久才读懂。
关键在于如何建图。
将在第0列可以看做第0个点,第n列可以看做第m+1个点。
这两个特殊的点到其他点的距离为点线垂直距离,其他的点之间的距离为点点距。
还有不同的地方就是两个信号塔之间的距离是两个半径,而0点和m+1点到其他点的距离一个半径,建图时将其中一个除以2或者另一个乘2即可。

AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
using namespace std;
const int maxn=1005;
int n,m,fa[maxn],cnt;
double ans;
struct node{
	int u,v;
	double w;
}e[maxn*maxn];
struct Node{
	double x,y;
}a[maxn];
bool cmp(node a,node b){
	return a.w<b.w;
}
int find(int x){
	if(fa[x]==x) return x;
	return fa[x]=find(fa[x]);
}
double getdis(int i,int j){
	return sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y))/2;
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=0;i<=m+1;i++) fa[i]=i;
	for(int i=1;i<=m;i++){
		cin>>a[i].x>>a[i].y;
	}
	for(int i=1;i<=m;i++) {
		e[++cnt].u=0;
		e[cnt].v=i;
		e[cnt].w=a[i].x;
		
		e[++cnt].u=i;
		e[cnt].v=m+1;
		e[cnt].w=(n-a[i].x);
	}
	for(int i=1;i<m;i++){
		for(int j=i+1;j<=m;j++){
			e[++cnt].u=i;
			e[cnt].v=j;
			e[cnt].w=getdis(i,j);
		}
	}
	sort(e+1,e+cnt+1,cmp);
	for(int i=1;i<=cnt;i++){
		ans=e[i].w;
		int x=find(e[i].u),y=find(e[i].v);
		if(x!=y){
			fa[x]=y;
		}
		if(find(0)==find(m+1)) break;
	}
	cout<<fixed<<setprecision(2)<<ans;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章