【洛谷】P1783 海滩防御(最小生成树+思维)

题目链接

本来以为是一道计算几何,然后看大佬的代码发现竟然是最小生成树??
能想到最小生成树很诡异,建图也很诡异。
最后相当于求0-n+1的这条路上的最大边权。

列数就是该点的横坐标。

建完图套一下Krustra的板子就好了。

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
#define clr(s, x) memset(s, x, sizeof(s))
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
inline int read(){int r=0;char c=getchar();while(c<'0'||c>'9') {c=getchar();}while(c>='0'&&c<='9') {r=r*10+c-'0';c=getchar();}return r;}
inline ll readll(){ll r=0;char c=getchar();while(c<'0'||c>'9') {c=getchar();}while(c>='0'&&c<='9') {r=r*10+c-'0';c=getchar();}return r;}
inline ll qpow(ll a,ll b,ll mod){ll res=1;while(b){if(b&1)res = (res*a)%mod;a=(a*a)%mod;b>>=1;}return res;}
inline ll gcd(ll a,ll b){while(b^=a^=b^=a%=b);return a;}
const double eps = 1e-8;
const ll LLINF = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const int MAXN = 1e5;
const int MAXM = 1e5;

struct EDGE{
	int u, v;
	double w;
};
bool cmp(EDGE a, EDGE b){
	return a.w < b.w;
}
vector<EDGE> G;
double x[MAXN], y[MAXN];
int pre[MAXN];
double dist(int i, int j){
	return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
int find(int x){
	if(x == pre[x])	return x;
	else	return pre[x] = find(pre[x]);
}
void merge(int x, int y){
	int fx = find(x);
	int fy = find(y);
	if(fx != fy)	pre[fx] = fy;
}
int main(int argc, char const *argv[])
{
	ios::sync_with_stdio(false);
	double l;
	int n;
	G.clear();
	cin >> l >> n;
	for(int i=1; i<=n; ++i)	cin >> x[i] >> y[i];
	for(int i=1; i<n; ++i){
		for(int j=i+1; j<=n; ++j){
			G.push_back((EDGE){i, j, dist(i,j)/2.0});
		}
	}
	for(int i=1; i<=n; ++i){
		G.push_back((EDGE){i, 0, x[i]});
		G.push_back((EDGE){i, n+1, l-x[i]});
	}
	sort(G.begin(),G.end(),cmp);
	for(int i=0; i<=n+1; ++i)	pre[i] = i;
	for(int i=0; ; ++i){
		merge(G[i].u, G[i].v);
		if(find(0) == find(n+1)){
			cout << fixed << setprecision(2) << G[i].w <<endl;
			break;
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41009682/article/details/82846242
今日推荐