题目大意:
南极有n个科研站, 要把这些站用卫星或者无线电连接起来,使得任意两个都能直接或者间接相连。任意两个都有安装卫星设备的,都可以直接通过卫星通信,不管它们距离有多远。 而安装有无线电设备的两个站,距离不能超过D。 D越长费用越多。
现在有s个卫星设备可以安装,还有足够多的无线电设备,求一个方案,使得费用D最少(D取决与所有用无线电通信的花费最大的那条路径)。

分析与总结:
很自然的想到求最小生成树,然后为了使得D费用最少,就要让其中路径最长的那些用来安装卫星。 s个通信卫星可以安装s-1条最长的那些路径。 那么, 最小生成树中第p-s大的路径长度就是D。
只需要求出最小生成树上的所有路径长度,排好序,边得到答案。

CODE:

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;

#define MAXN 1100
#define INF 0X3F3F3F3F

int n, k, m;

struct node
{
    double x, y;
}a[MAXN*MAXN];

struct Edge
{
    int u, v;
    double w;
}edge[MAXN*MAXN];

int p[MAXN], tot;

int cmp(const Edge a, const Edge b)
{
    return a.w < b.w;
}

double w[MAXN][MAXN], d[MAXN];

void init()
{
    tot = 0;
}

double dist(const node a, const node b)
{
    return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}

int find(int x)

    return x == p[x]? x : p[x] = find(p[x]);
}

void Kruskal()
{
    double ans = 0;
    int count = 0;
    for(int i = 0; i <= n; i++) p[i] = i;
    sort(edge, edge+tot, cmp);
    for(int i = 0; i < tot; i++)
    {
        int x = find(edge[i].u), y = find(edge[i].v);
        if(x != y)
        {
            ans = edge[i].w;
            p[x] = y;
            count++;
        }
        if(count == n-m)
        {
            printf("%.2lf\n", ans);
            return ;
        }
    }
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        init();
        scanf("%d%d", &m, &n);
        for(int i = 1; i <= n; i++) scanf("%lf%lf", &a[i].x, &a[i].y);
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= n; j++) if(i != j)
            {
                edge[tot].u = i, edge[tot].v = j;
                edge[tot].w = dist(a[i], a[j]);
                tot++;
            }
        }
        Kruskal();
    }
    return 0;
}

 

posted on 2012-10-25 19:09  有间博客  阅读(237)  评论(0编辑  收藏  举报