【题解】Arctic Network POJ - 2349 ⭐⭐⭐ 【Krusal】

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值