Arctic Network POJ - 2349
国防部(DND)要用无线网络连接北部几个哨所。两种不同的通信技术被用于建立网络:每一个哨所有一个无线电收发器,一些哨所将有一个卫星频道。
任何两个有卫星信道的哨所可以通过卫星进行通信,而不管他们的位置。同时,当两个哨所之间的距离不超过D时可以通过无线电通讯,D取决于对收发器的功率。功率越大,D也越大,但成本更高。出于采购和维修的方便,所有哨所的收发器必须是相同的;那就是说,D值对每一个哨所相同。
你的任务是确定收发器的D的最小值。每对哨所间至少要有一条通信线路(直接或间接)。
Input
输入的第一行是测试数据的数量N。
每组测试数据的第一行包含卫星频道的数量S(1 < = S < = 100)和哨所的数量P(S < P < = 500)。接下来的P行,给出以公里为单位的每个哨所的坐标(x,y)( 坐标为0到10000之间的整数)。
Output
对于每组测试数据,输出一行,输出收发器的D的最小值。精确到小数点后两位。
Examples
Sample Input
1
2 4
0 100
0 300
0 600
150 750
Sample Output
212.13
Hint
题意:
题解:
选择S个点, 使得S-1条边权值为0, 毫无疑问要想求得更新的D值, 我们一定要把最大的边给变0
因为是稀疏图, 而且是对边操作, Kruskal又能单调递增, 此题使用Kruskal肯定更为方便
我们依次存一下加入到MST的每条边, 最终答案就是mst[P-S-1]
经验小结:
G++输出用%f, C++用%lf
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef long long LL;
const int inf = 1 << 30;
const LL maxn = 510;
int S, N, M;
double w[maxn][maxn];
struct Vertex {
int x, y;
Vertex(int xx, int yy) {x = xx, y = yy;}
Vertex() {}
} vs[maxn];
struct Edge {
int u, v;
double d;
Edge(int uu, int vv, double dd) {u = uu, v = vv, d = dd;}
Edge() {}
}es[maxn*maxn];
double getDis(int x1, int y1, int x2, int y2) {
return sqrt((double)(x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
int par[maxn], rak[maxn];
void init(int n) {
for(int i = 0; i <= n; i++)
par[i] = i, rak[i] = 0;
}
int findr(int x) {
if(x == par[x])
return x;
else
return par[x] = findr(par[x]);
}
bool isSame(int x, int y) {
return findr(x) == findr(y);
}
void unite(int x, int y) {
x = findr(x), y = findr(y);
if(x == y)
return;
if(rak[x] < rak[y])
par[x] = y;
else {
par[y] = x;
if(rak[x] == rak[y])
++rak[x];
}
}
bool cmp(const Edge &a, const Edge &b) {return a.d < b.d;}
vector<double> mst; //MST中的边
void Kruskal() {
sort(es+1, es+1+M, cmp); //对边排序
init(N); //以点为元素做并查集初始化
mst.clear();
for(int i = 1; i <= M; i++) {
Edge cur = es[i];
if(!isSame(cur.u, cur.v)) {
unite(cur.u, cur.v);//只要不是同一连通分量即归入生成树
mst.push_back(cur.d);
}
}
}
int main() {
int T;
cin >> T;
while(T--) {
cin >> S >> N;
for(int i = 1; i <= N; ++i)
cin >> vs[i].x >> vs[i].y;
M = 0;
for(int i = 1; i < N; ++i)
for(int j = i + 1; j <= N; ++j)
es[++M] = Edge(i, j, getDis(vs[i].x, vs[i].y, vs[j].x, vs[j].y));
Kruskal();
printf("%.2f\n", mst[N-S-1]);
}
return 0;
}