描述:有N(N2+ (y_j-y_i)2 + (z_j-z_i)2。请求出最大的t,使得N个网页可以聚成K类,其中每个类至少包含一个网页,且任意两个位于不同类中网页的相似度都至少为t。
输入
第一行包含两个整数N和K,后面N行每行三列,分别为x、y、z。
输出
最大的t的值,使用四舍五入在小数点后保留六位小数。
样例输入
5 3
0.1 0.2 0.4
0.2 0.8 0.7
0.3 0.4 0.5
0.0 0.5 0.0
0.3 0.3 0.2
样例输出
0.170000
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
const int MAXN = 2010;
const double EPS = 1e-8;
double x[MAXN], y[MAXN], z[MAXN], d[MAXN][MAXN];
bool vis[MAXN];
int n, k, cnt, belong[MAXN];
queue <int> q;
vector <int> e[MAXN];
vector <int> :: iterator iter;
double dist(int i, int j)
{
return (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]) + (z[i] - z[j]) * (z[i] - z[j]);
}
void bfs(int p)
{
memset(vis , 0 , sizeof(vis));
q.push(p);
while (!q.empty())
{
int u = q.front();
q.pop();
belong[u] = cnt, vis[u] = true;
for(iter = e[u].begin(); iter != e[u].end(); ++iter)
{
if (!vis[*iter])
q.push(*iter);
}
}
}
bool check(double t)
{
int i, j;
for (i = 0; i < n; ++i)
{
e[i].clear();
for (j = 0; j < n; ++j)
{
if (d[i][j] < t && i != j)
{
e[i].push_back(j);
}
}
}
cnt = 0;
for (i = 0; i < n; ++i)
{
if (!belong[i])
{
cnt++;
bfs(i);
}
}
return cnt >= k;
}
int main(void)
{
int i, j;
scanf("%d %d", &n, &k);
for (i = 0; i < n; ++i)
{
scanf("%lf %lf %lf", &x[i], &y[i], &z[i]);
}
for (i = 0; i < n; ++i)
{
for (j = 0; j < n; ++j)
{
d[i][j] = dist(i, j);
}
}
double l = 0, r = 3;
while (r - l > EPS)
{
memset(belong , 0 , sizeof(belong));
double mid = (l + r) / 2;
if( check(mid) )
l = mid;
else
r = mid;
}
printf("%.6lf\n", l);
return 0;
}