题意: 从n个点中选取k个点,使得在选取的所有边的距离中最短的最长,求出这个距离。
如果看成一个图的话就可以全部连边成完全图,就可以二分答案用最大团去做。
图论真的是模板效率重要哇,刚一开始我的板子一直t。。。
链接:hdu - 3585
AC代码:
/*
最大团 = 补图G的最大独立集数
———>最大独立集数 = 补图G'最大团
*/
//最大团模板
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 105;
int mx;//最大团数(要初始化为0)
int vis[maxn], tuan[maxn];
int can[maxn][maxn];//can[i]表示在已经确定了经选定的i个点必须在最大团内的前提下还有可能被加进最大团的结点集合
int num[maxn];//num[i]表示由结点i到结点n构成的最大团的结点数
bool g[maxn][maxn];//邻接矩阵(从1开始)
int n, m;
bool dfs(int tot, int cnt) {
if(tot == 0) {
if(cnt > mx) {
mx = cnt;
for(int i = 0; i < mx; i++) {
tuan[i] = vis[i];
}
return true;
}
return false;
}
for(int i = 0; i < tot; i++) {
if(cnt + (tot - i) <= mx) return false;
if(cnt + num[can[cnt][i]] <= mx) return false;
int k = 0;
vis[cnt] = can[cnt][i];
for(int j = i + 1; j < tot; j++) {
if(g[can[cnt][i]][can[cnt][j]]) {
can[cnt + 1][k++] = can[cnt][j];
}
}
if(dfs(k, cnt + 1)) return false;
}
return false;
}
void maxclique() {
mx = 1;
for(int i = n; i >= 1; i--) {
int k = 0;
vis[0] = i;
for(int j = i + 1; j <= n; j++) {
if(g[i][j]) {
can[1][k++] = j;
}
}
dfs(k, 1);
num[i] = mx;
}
}
int x[maxn], y[maxn];
int s[maxn][maxn];
int dist(int i, int j) {
return (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]);
}
int main()
{
int k;
while(~scanf("%d %d", &n, &k)) {
memset(s, 0, sizeof(s));
int l = 0, r = 0;
for(int i = 1; i <= n; i++) {
scanf ("%d %d", &x[i], &y[i]);
for(int j = 1; j < i; j++) {
s[i][j] = s[j][i] = dist(i, j);
if(r < s[i][j])
r = s[i][j];
}
}
//cout << r << endl;
int mid;
while(l <= r) {
memset(g, 0, sizeof(g));
for(int i = 1; i <= n; i++) {
for(int j = 1; j < i; j++) {
if(s[i][j] >= mid) {
g[i][j] = g[j][i] = 1;
}
}
}
maxclique();//求最大团
if(mx >= k) {
l = mid + 1;
}
else if(mx < k) {
r = mid - 1;
}
mid = (l + r) / 2;
}
//cout << mid << endl;
printf("%.2lf\n", sqrt(mid));
/*for(int i = 0; i < mx; i++)
printf( i == 0 ? "%d" : " %d", group[i]); //group[maxn]用以寻找一个最大团集合
if( ans > 0 ) puts("");*/
}
}