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; }