POJ2349 Arctic Network

原题链接

先随便找一棵最小生成树,然后贪心的从大到小选择边,使其没有贡献。
显然固定生成树最长边的一个端点安装卫星频道后,从大到小选择边的一个端点作为卫星频道即可将该边的贡献去除。
所以最后的答案就是最小生成树上第(m)长的边。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int N = 510;
struct cod {
	int x, y;
};
cod a[N];
int n;
double eg[N][N], dis[N];
bool v[N];
inline int re()
{
	int x = 0;
	char c = getchar();
	bool p = 0;
	for (; c < '0' || c > '9'; c = getchar())
		p |= c == '-';
	for (; c >= '0' && c <= '9'; c = getchar())
		x = x * 10 + c - '0';
	return p ? -x : x;
}
inline double minn(double x, double y)
{
	return x < y ? x : y;
}
void prim()
{
	int i, j, x;
	memset(dis, 65, sizeof(dis));
	memset(v, 0, sizeof(v));
	dis[1] = 0;
	for (i = 1; i <= n; i++)
	{
		x = 0;
		for (j = 1; j <= n; j++)
			if (!v[j] && (!x || dis[j] < dis[x]))
				x = j;
		if (!x)
			break;
		v[x] = 1;
		for (j = 1; j <= n; j++)
			if (!v[j])
				dis[j] = minn(dis[j], eg[x][j]);
	}
}
int main()
{
	int i, j, m, t;
	t = re();
	while (t--)
	{
		m = re();
		n = re();
		for (i = 1; i <= n; i++)
		{
			a[i].x = re();
			a[i].y = re();
		}
		for (i = 1; i < n; i++)
			for (j = i + 1; j <= n; j++)
				eg[j][i] = eg[i][j] = sqrt(1.0 * (a[i].x - a[j].x) * (a[i].x - a[j].x) + 1.0 * (a[i].y - a[j].y) * (a[i].y - a[j].y));
		prim();
		sort(dis + 1, dis + n + 1);
		printf("%.2f
", dis[n - m + 1]);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9696580.html