题意:
某地区共有n座村庄,每座村庄的坐标用一对整数(x, y)表示,现在要在村庄之间建立通讯网络。
通讯工具有两种,分别是需要铺设的普通线路和无线通讯的卫星设备。
只能给k个村庄配备卫星设备,拥有卫星设备的村庄互相间直接通讯。
铺设了线路的村庄之间也可以通讯。但是由于技术原因,两个村庄之间线路长度最多不能超过 d, 否则就会由于信号衰减导致通讯不可靠。要想增大 d 值,则会导致要投入更多的设备(成本)。
已知所有村庄的坐标 (x , y) ,卫星设备的数量 k 。
问:如何分配卫星设备,才能使各个村庄之间能直接或间接的通讯,并且 d 的值最小?求出 d 的最小值。
数据规模:0 <= k <= n<= 500
思路:
只需找到一个最小的d,使得连通支的个数小于等于卫星设备的数目。把整个问题看做一个完全图,只需在该图上求最小生成树,d 的最小值即为第 K 长边。因为:最小生成树中的最长k-1条长边都去掉后,正好将原树分成了k 个连通分支,在每个连通分支上摆一个卫星设备即可。
实现:
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 struct node 8 { 9 int x, y; 10 }; 11 struct edge 12 { 13 int a, b; 14 double cost; 15 }; 16 vector<node> ns; 17 vector<edge> es; 18 int ran[505]; 19 int par[505]; 20 int t, k, n, x, y; 21 22 int square(int x) 23 { 24 return x * x; 25 } 26 27 bool cmp1(const double & x, const double & y) 28 { 29 return x > y; 30 } 31 32 void init(int n) 33 { 34 for (int i = 0; i < n; i++) 35 { 36 par[i] = i; 37 ran[i] = 0; 38 } 39 } 40 int find(int x) 41 { 42 if (par[x] == x) 43 return x; 44 return par[x] = find(par[x]); 45 } 46 void unite(int x, int y) 47 { 48 x = find(x); 49 y = find(y); 50 if (x == y) 51 return; 52 if (ran[x] < ran[y]) 53 { 54 par[x] = y; 55 } 56 else 57 { 58 par[y] = x; 59 if (ran[x] == ran[y]) 60 { 61 ran[x] ++; 62 } 63 } 64 } 65 bool same(int x, int y) 66 { 67 return find(x) == find(y); 68 } 69 70 bool cmp(edge a, edge b) 71 { 72 return a.cost < b.cost; 73 } 74 75 void kru(vector<double> & res, int m) 76 { 77 init(n); 78 sort(es.begin(), es.end(), cmp); 79 for (int i = 0; i < m; i++) 80 { 81 if (!same(es[i].a, es[i].b)) 82 { 83 unite(es[i].a, es[i].b); 84 res.push_back(es[i].cost); 85 } 86 } 87 } 88 89 int main() 90 { 91 cin >> t; 92 while (t--) 93 { 94 ns.clear(); 95 es.clear(); 96 cin >> k >> n; 97 for (int i = 0; i < n; i++) 98 { 99 cin >> x >> y; 100 node tmp; 101 tmp.x = x; 102 tmp.y = y; 103 ns.push_back(tmp); 104 } 105 for (int i = 0; i < ns.size(); i++) 106 { 107 for (int j = i + 1; j < ns.size(); j++) 108 { 109 edge e; 110 e.a = i; 111 e.b = j; 112 e.cost = sqrt(square(ns[i].x - ns[j].x) + square(ns[i].y - ns[j].y)); 113 es.push_back(e); 114 e.a = j; 115 e.b = i; 116 es.push_back(e); 117 } 118 } 119 vector<double> res; 120 kru(res, es.size()); 121 sort(res.begin(), res.end(), cmp1); 122 printf("%.2f\n", res[k - 1]); 123 } 124 return 0; 125 }
总结:
还有次小生成树、最大生成树等
时间: 2024-09-30 18:33:00