洛谷 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章