• 【最小生成树-第k大边】Arctic Network POJ


    Arctic Network POJ - 2349

    相似题目:POJ 2253 Frogger

    题意:

    给定(p)个哨所的坐标,可任意使其中(s)个拥有卫星通讯功能。任意两个具有卫星通讯功能的哨所视为连通。在剩下的哨所之间建立无线电路径,路径的花费(D)为哨所之间的距离。求能使所有哨所连通的最小的(D)

    思路:

    如果忽略卫星通讯这个条件,题目所求的明显是最小生成树的最大边。

    加上卫星通讯这个条件,就相当于可以使最小生成树中的任意(s-1)条边免费,再在剩下不免费的边中找出花费最大的那一条。

    结合题意,将最小生成树的所有边从大到小排序,使前(s-1)条边免费,那么第(s)条边的花费就是答案了。

    差点就1A了,但是因为把500*500算成了25000导致数组开小了而RE了一发……

    int fa[maxn];
    int tmp1[maxn], tmp2[maxn];
    int u[maxn], v[maxn];
    double w[maxn];
    double edge[maxn];
    int n, m, m2, k;
    
    struct node {
        double x, y;
    }N[maxn];
    
    int find(int x) { 
        return fa[x] == x ? x : fa[x] = find(fa[x]); 
    }
    bool cmp1(int i, int j) {
        return w[i] < w[j];
    }
    
    bool cmp2(int i, int j) {
        return edge[i] > edge[j];
    }
    
    double count(node t1, node t2) {
        double dx = t1.x - t2.x;
        double dy = t1.y - t2.y;
        return sqrt(dx * dx + dy * dy);
    }
    
    double solve() {
       // double ans = 0;
        for (int i = 0; i < maxn; i++) fa[i] = i;
        for (int i = 0; i < m; i++) tmp1[i] = i;
        for (int i = 0; i < m; i++) tmp2[i] = i;
        sort(tmp1, tmp1 + m, cmp1);
        //板子内容,将备选的所有边从小到大排序,以便计算最小生成树
        for (int i = 0; i < m; i++) {
            int e = tmp1[i];
            int from = find(u[e]);
            int to = find(v[e]);
            if (from != to) {
               // ans += w[e];
                edge[m2++] = w[e];
                //记录最小生成树中边的花费
                fa[from] = to;
            }
        }
        sort(tmp2, tmp2 + m2, cmp2);
        //将最小生成树中的所有边从大到小排序,只将结果以下标形式保存在tmp2中
        return edge[tmp2[k-1]];
        //注意tmp2下标从0开始,第x大的边下标为x-1
        //题目给定的卫星信道不是边,是拥有该功能的点的数量
        //k个卫星信道形成k-1条边,所以要求的是树中第k大条边
       // return ans;
    }
    
    int main()
    {
        //ios::sync_with_stdio(false);
        int t; cin >> t; while (t--) {
            m = 0;
            m2 = 0;
            cin >> k >> n;
            for (int i = 1; i <= n; i++) {
                cin >> N[i].x >> N[i].y;
                for (int j = i-1 ; j >= 1; j--) {
                    double tp = count(N[i], N[j]);
                    u[m] = i; v[m] = j; w[m] = tp; m++;
                    u[m] = j; v[m] = i; w[m] = tp; m++;
                }
            }
            printf("%.2f
    ", solve());
        }
        return 0;
    }
    
  • 相关阅读:
    常见加密算法概述
    IDEA常见错误解决
    linux Find命令教程
    用注册表更改DNS的代码分享
    关于javascript中的typeof和instanceof介绍
    javascript instanceof,typeof的区别
    Javascript typeof 用法
    浅析JavaScript中的typeof运算符
    玩转Linux文件描述符和重定向
    shell脚本 批量转换目录下文件编码
  • 原文地址:https://www.cnblogs.com/streamazure/p/13503422.html
Copyright © 2020-2023  润新知