zoukankan      html  css  js  c++  java
  • 【最小生成树-第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;
    }
    
  • 相关阅读:
    B-S 期权定价模型
    可转债溢价率
    队列模拟递归遍历目录(广度遍历)
    栈模拟递归遍历目录(深度遍历)
    什么人适合学习Django?
    Python学习笔记———递归遍历多层目录
    树莓派开机自启动程序的设置,两步即可。
    7行代码对百万张照片统一改名。
    tornado上帝视角第一次建立WEB服务器
    武沛齐模态对话框课堂作业
  • 原文地址:https://www.cnblogs.com/streamazure/p/13503422.html
Copyright © 2011-2022 走看看