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

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\n", solve());
    }
    return 0;
}
posted @ 2020-08-14 17:26  StreamAzure  阅读(111)  评论(0编辑  收藏  举报