uva 10369 Arctic Network

最小生成树入门题

题意:有n个点给出坐标,点和点之间可以用无线电或者卫星通信,每个点都有无线电收发器可进行无线电通信,但是只有m个点有卫星通信功能。卫星通信的距离可以无限大,但无线电通信的距离不能超过D,超过D的部分将使通信费用增加。要使通信费用最少。

其实就是求一次最小生成树,m个点有卫星通信,那么就会有m-1条边的通信距离无限大,其实就是这m-1条边不用计算费用。而剩下的边中,找出最大边作为D值,这样剩下的所有的边都不会大于D,那么不会增加通信费用。在构建MST过程中保存下所有的边权值,然后按升序排序,除掉最后的m-1条边(也就是最大的m-1条边,这些边用卫星通信),最大的那条就是D

 

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 510
#define INF 1000000000.000
double g[N][N];
int x[N],y[N];
int n,m;  //有m个卫星

double dis(int i ,int j)
{ return sqrt( 1.*(x[i]-x[j])*(x[i]-x[j])+1.*(y[i]-y[j])*(y[i]-y[j]) ); }


void prim()
{
    double lowcost[N],ans[N];
    int adj[N],cov[N];
    for(int i=2; i<=n; i++)
    {
        lowcost[i]=g[1][i];
        adj[i]=1;
        cov[i]=0;
    }
    lowcost[1]=0;  adj[1]=1; cov[1]=1;

    for(int nn=1; nn<n; nn++)  //还有纳入n-1个点
    {
        double min=INF;
        int k=1;
        for(int i=1; i<=n; i++) 
            if(!cov[i] && lowcost[i]<min)
            {
                min=lowcost[i];
                k=i;
            }
        //printf("%.2f\n",min);
        ans[nn]=min;
        cov[k]=1;

        for(int i=1; i<=n; i++)
            if(!cov[i] && lowcost[i] > g[k][i])
            {
                lowcost[i]=g[k][i];
                adj[i]=k;
            }
    }
    
    sort(ans+1 , ans+n);
/*
    for(int i=1; i<n; i++)
        printf("%.2f\n",ans[i]);
*/
    printf("%.2lf\n",ans[n-m]);
    return ;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&m,&n);
        for(int i=1; i<=n; i++)
            scanf("%d%d",&x[i],&y[i]);

        for(int i=1; i<=n; i++) g[i][i]=0;

        for(int i=1; i<=n; i++)
            for(int j=i+1; j<=n; j++)
                g[i][j]=g[j][i]=dis(i,j);

        prim();
    }
    return 0;
}

 

posted @ 2012-12-19 09:11  Titanium  阅读(706)  评论(1编辑  收藏  举报