P1991 无线通讯网

解题思路

问题重述

我们需要连接P个边防哨所,其中有S个可以配备卫星电话(任意距离通信),其余哨所需要通过无线电收发器连接(距离不超过D)。目标是找到最小的D,使得所有哨所都能互相通信。

关键思路

  1. 最小生成树(MST)变形:本质上是要构建一个生成树,其中可以用S-1条卫星电话连接替代最贵的S-1条边

  2. D的确定:在最小生成树中,第(P-S)大的边的长度就是所需的最小D

    • 因为最大的S-1条边可以用卫星电话替代

    • 剩下的最长边就是无线电需要的最大距离D

算法选择

  1. Kruskal算法:适合处理边排序和连通性问题

  2. 修改策略:在构建MST时,只需要选择(P-S)条边而非传统的(P-1)条

实现步骤

  1. 计算所有边:生成完全图,计算每对哨所间的距离

  2. 边排序:按距离从小到大排序

  3. 修改的Kruskal

    • 使用并查集管理连通分量

    • 只选择前(P-S)条最短的有效边

    • 记录这些边中的最大值作为D

  4. 输出结果:保留两位小数输出D

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;

// 边结构体:存储两个哨所编号和它们之间的距离
struct node {
    int x, y;
    double z;
};

node t[N];    // 存储所有可能的边
int x[N], y[N]; // 存储每个哨所的坐标
int f[N];     // 并查集数组
int s, p, cnt; // s:卫星电话数量, p:哨所数量, cnt:边数
int sum;      // 已选边数计数器
double ans;   // 最终结果(最小D值)

// 计算两点间欧氏距离
double dis(int i, int j) {
    return sqrt((x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]));
}

// 边按距离从小到大排序的比较函数
bool cmp(node a, node b) {
    return a.z < b.z;
}

// 并查集查找函数(带路径压缩)
int find(int x) {
    if(f[x] != x) f[x] = find(f[x]);
    return f[x];
}

// 并查集合并函数
void merge(int x, int y) {
    int fx = find(x), fy = find(y);
    f[fy] = fx;
}

// Kruskal算法主函数(修改版)
void Kruskal() {
    for(int i = 1; i <= cnt; i++) {
        int u = t[i].x, v = t[i].y;
        if(find(u) != find(v)) {  // 如果不在同一连通块
            merge(u, v);          // 合并
            sum++;                // 边数增加
            ans = max(ans, t[i].z); // 更新当前最大边
            if(sum == p - s) break; // 关键点:只需要选p-s条边
        }
    }
}

int main() {
    cin >> s >> p;
    // 初始化并查集和读取坐标
    for(int i = 1; i <= p; i++) {
        cin >> x[i] >> y[i];
        f[i] = i;
    }
    
    // 生成所有可能的边
    for(int i = 1; i <= p; i++) {
        for(int j = i + 1; j <= p; j++) {
            t[++cnt] = {i, j, dis(i,j)};
        }
    }
    
    // 按边权升序排序
    sort(t + 1, t + 1 + cnt, cmp);
    
    // 执行修改后的Kruskal算法
    Kruskal();
    
    // 输出结果(保留两位小数)
    printf("%.2f", ans);
    return 0;
}

 

posted @ 2025-04-28 21:29  CRt0729  阅读(19)  评论(0)    收藏  举报