luogu1991 无线通讯网

题目大意

  国防部计划用无线网络连接若干个边防哨所。2 种不同的通讯技术用来搭建无线网络;每个边防哨所都要配备无线电收发器;有一些哨所还可以增配卫星电话。任意两个配备了一条卫星电话线路的哨所(两边都ᤕ有卫星电话)均可以通话,无论他们相距多远。而只通过无线电收发器通话的哨所之间的距离不能超过 D,这是受收发器的功率限制。收发器的功率越高,通话距离 D 会更远,但同时价格也会更贵。收发器需要统一购买和安装,所以全部哨所只能选择安装一种型号的收发器。换句话说,每一对哨所之间的通话距离都是同一个 D。你的任务是确定收发器必须的最小通话距离 D,使得每一对哨所之间至少有一条通话路径(直接的或者间接的)。

题解

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

const int MAX_NODE = 510, MAX_EDGE = MAX_NODE * MAX_NODE;

struct Node
{
	int X, Y;
	Node *Father;
}_nodes[MAX_NODE];
int TotNode, S;

struct Edge
{
	Node *From, *To;
	double Weight;

	bool operator < (const Edge& a) const
	{
		return Weight < a.Weight;
	}
}_edges[MAX_EDGE];
int _eCount;

double Dist(Node& a, Node& b)
{
	int dx = a.X - b.X, dy = a.Y - b.Y;
	return sqrt(dx * dx + dy * dy);
}

Node *FindRoot(Node *cur)
{
	return cur->Father == cur ? cur : cur->Father = FindRoot(cur->Father);
}

double Kruskal()
{
	for (int i = 1; i <= TotNode; i++)
		_nodes[i].Father = _nodes + i;
	sort(_edges + 1, _edges + _eCount + 1);
	int cnt = 0;
	for (int i = 1; i <= _eCount; i++)
	{
		Edge *e = _edges + i;
		Node *root1 = FindRoot(e->From), *root2 = FindRoot(e->To);
		if (root1 != root2)
		{
			root1->Father = root2;
			cnt++;
			if (cnt == TotNode - S)
				return e->Weight;
		}
	}
	return -1;
}

int main()
{
	scanf("%d%d", &S, &TotNode);
	for (int i = 1; i <= TotNode; i++)
		scanf("%d%d", &_nodes[i].X, &_nodes[i].Y);
	for (int i = 1; i <= TotNode; i++)
		for (int j = i + 1; j <= TotNode; j++)
		{
			Edge *e = _edges + ++_eCount;
			e->From = _nodes + i;
			e->To = _nodes + j;
			e->Weight = Dist(_nodes[i], _nodes[j]);
		}
	printf("%.2f\n", Kruskal());
	return 0;
}

  

posted @ 2018-08-12 15:40  headboy2002  阅读(104)  评论(0编辑  收藏  举报