卧薪尝胆,厚积薄发。
JSOI2010 部落划分
Date: Wed Aug 01 15:26:09 CST 2018 In Category: NoCategory

Description:

将一些点划分成 $k$ 部分,使得各部分之间最近的两个点最远。
$1\le n \le 1000$

Solution:

处理出各个点之间的距离 $kruskal$ 合并即可。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,k;
#define MAXN 1010
double x[MAXN],y[MAXN];
struct edge
{
int u,v;
double d;
}e[MAXN * MAXN];
int edgenum = 0;
inline void add(int a,int b,double c){++edgenum;e[edgenum].u = a;e[edgenum].v = b;e[edgenum].d = c;return;}
inline double dis(int a,int b){return sqrt((x[a] - x[b]) * (x[a] - x[b]) + (y[a] - y[b]) * (y[a] - y[b]));}
int f[MAXN];
int find(int x){return (x == f[x] ? x : f[x] = find(f[x]));}
bool cmp(edge a,edge b){return a.d < b.d;}
int main()
{
scanf("%d%d",&n,&k);
for(int i = 1;i <= n;++i)
{
scanf("%lf%lf",&x[i],&y[i]);
}
for(int i = 1;i <= n;++i)
{
for(int j = i + 1;j <= n;++j)
{
add(i,j,dis(i,j));
}
}
for(int i = 1;i <= n;++i)
{
f[i] = i;
}
int siz = n;
sort(e + 1,e + 1 + edgenum,cmp);
int i;
for(i = 1;i <= edgenum && siz != k;++i)
{
if(find(e[i].u) == find(e[i].v))continue;
f[find(e[i].u)] = find(e[i].v);
--siz;
}
while(find(e[i].u) == find(e[i].v))++i;
printf("%.2f\n",e[i].d);
return 0;
}
In tag: 图论-kruskal
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡