天天看點

HDU 3656 Fire station

Problem Description

A city's map can be seen as a two dimensional plane. There are N houses in the city and these houses can be seen as N points P

1 …… P

N on the two dimensional plane. For simplicity's sake, assume that the time spent from one house number to another is equal to the distance between two points corresponding to the house numbers. The government decides to build M fire stations from N houses. (If a station is build in Pi, We can think the station is next to the house and the time from the station to the house is considered zero.) It is obvious that if some place such as Pi is breaking out of fire, the nearest station will dispatched a fire engine quickly rushed to the rescue scene. The time it takes from this station to the rescue scene is called rescue time. Now you need to consider about a problem that how to choice the positions of the M fire station to minimize the max rescue time of all the houses.

Input

The fi rst line of the input contains one integer T, where T is the number of cases. For each case, the fi rst line of each case contains two integers N and M separated by spaces (1 ≤ M ≤N ≤ 50), where N is the number of houses and M is the number of fire stations. Then N lines is following. The ith line contains two integers Xi and Yi (0 ≤ Xi, Yi ≤ 10000), which stands for the coordinate of the ith house.

Output

The rescue time which makes the max rescue time is minimum.

Sample Input

2

4 2

1 1

1 2

2 3

2 4

4 1

1 1

1 2

2 3

2 4

Sample Output

1.000000

2.236068

dlx重複覆寫+二分距離

#include<cstdio>
#include<vector>
#include<cmath>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll maxn = 105;
int T, n, m, x, y, t, tot, X[maxn], Y[maxn], l, r, mid;
double mp[maxn][maxn], dis[maxn*maxn];

inline void read(int &ret)
{
	char c;
	do {
		c = getchar();
	} while (c < '0' || c > '9');
	ret = c - '0';
	while ((c = getchar()) >= '0' && c <= '9')
		ret = ret * 10 + (c - '0');
}

struct DLX
{
#define maxn 500005
#define F(i,A,s) for (int i=A[s];i!=s;i=A[i])
	int L[maxn], R[maxn], U[maxn], D[maxn];
	int row[maxn], col[maxn], ans[maxn], cnt[maxn];
	int n, m, num, sz;

	void add(int now, int l, int r, int u, int d, int x, int y)
	{
		L[now] = l;	R[now] = r;	U[now] = u;
		D[now] = d;   row[now] = x;  col[now] = y;
	}
	void reset(int n, int m)
	{
		num = 0x7FFFFFFF;
		this->n = n;	this->m = m;
		for (int i = 0; i <= m; i++)
		{
			add(i, i - 1, i + 1, i, i, 0, i);
			cnt[i] = 0;
		}
		L[0] = m; 	R[m] = 0; 	sz = m + 1;
	}
	void insert(int x, int y)
	{
		int ft = sz - 1;
		if (row[ft] != x)
		{
			add(sz, sz, sz, U[y], y, x, y);
			U[D[sz]] = sz; D[U[sz]] = sz;
		}
		else
		{
			add(sz, ft, R[ft], U[y], y, x, y);
			R[L[sz]] = sz; L[R[sz]] = sz;
			U[D[sz]] = sz; D[U[sz]] = sz;
		}
		++cnt[y];	++sz;
	}

	//精确覆寫
	void remove(int now)
	{
		R[L[now]] = R[now];
		L[R[now]] = L[now];
		F(i, D, now) F(j, R, i)
		{
			D[U[j]] = D[j];
			U[D[j]] = U[j];
			--cnt[col[j]];
		}
	}
	void resume(int now)
	{
		F(i, U, now)	F(j, L, i)
		{
			D[U[j]] = j;
			U[D[j]] = j;
			++cnt[col[j]];
		}
		R[L[now]] = now;
		L[R[now]] = now;
	}
	bool dfs(int x)
	{
		//if (x + A() >= num) return;
		if (!R[0]) { num = min(num, x); return true; }
		int now = R[0];
		F(i, R, 0) if (cnt[now]>cnt[i]) now = i;
		remove(now);
		F(i, D, now)
		{
			ans[x] = row[i];
			F(j, R, i) remove(col[j]);
			if (dfs(x + 1)) return true;
			F(j, L, i) resume(col[j]);
		}
		resume(now);
		return false;
	}
	//精确覆寫

	//重複覆寫
	void Remove(int now)
	{
		F(i, D, now)
		{
			L[R[i]] = L[i];
			R[L[i]] = R[i];
		}
	}
	void Resume(int now)
	{
		F(i, U, now) L[R[i]] = R[L[i]] = i;
	}
	int vis[maxn];
	int flag[maxn];
	int A()
	{
		int dis = 0;
		F(i, R, 0) vis[i] = 0;
		F(i, R, 0) if (!vis[i])
		{
			dis++;	vis[i] = 1;
			F(j, D, i) F(k, R, j) vis[col[k]] = 1;
		}
		return dis;
	}
	void Dfs(int x)
	{
		if (!R[0]) num = min(num, x);
		else if (x + A()<num)
		{
			int now = R[0];
			F(i, R, 0) if (cnt[now]>cnt[i]) now = i;
			F(i, D, now)
			{
				Remove(i); F(j, R, i) Remove(j);
				Dfs(x + 1);
				F(j, L, i) Resume(j); Resume(i);
			}
		}
	}
	//重複覆寫
}dlx;

int main()
{
	read(T);
	while (T--)
	{
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= n; i++) scanf("%d%d", &X[i], &Y[i]);
		tot = 0;
		for (int i = 1; i <= n;i++)
			for (int j = 1; j <= n; j++)
			{
				mp[i][j] = sqrt((X[i] - X[j])*(X[i] - X[j]) + (Y[i] - Y[j])*(Y[i] - Y[j]));
				if (i < j || (i == j&&i == 1)) dis[tot++] = mp[i][j];
			}
		sort(dis, dis + tot);
		r = unique(dis, dis + tot) - dis - 1;
		for (l = 0; l < r;)
		{
			mid = (l + r) >> 1;
			dlx.reset(n, n);
			for (int i = 1; i <= n; i++)
				for (int j = 1; j <= n; j++)
					if (dis[mid] >= mp[i][j]) dlx.insert(i, j);
			dlx.Dfs(0);
			if (dlx.num > m) l = mid + 1; else r = mid;
		}
		printf("%.6lf\n", dis[l]);
	}
	return 0;
}