【2012百度之星/初赛下】B:网页聚类

来源:互联网 发布:河南禁止网络外卖 编辑:程序博客网 时间:2024/05/16 11:36

描述:有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;elser = mid;}printf("%.6lf\n", l);return 0;}