POJ 2349 (最小生成樹)

Description

The Department of National Defence (DND) wishes to connect several northern outposts by a wireless network. Two different communication technologies are to be used in establishing the network: every outpost will have a radio transceiver and some outposts will in addition have a satellite channel. 
Any two outposts with a satellite channel can communicate via the satellite, regardless of their location. Otherwise, two outposts can communicate by radio only if the distance between them does not exceed D, which depends of the power of the transceivers. Higher power yields higher D but costs more. Due to purchasing and maintenance considerations, the transceivers at the outposts must be identical; that is, the value of D is the same for every pair of outposts. 

Your job is to determine the minimum D required for the transceivers. There must be at least one communication path (direct or indirect) between every pair of outposts.

Input

The first line of input contains N, the number of test cases. The first line of each test case contains 1 <= S <= 100, the number of satellite channels, and S < P <= 500, the number of outposts. P lines follow, giving the (x,y) coordinates of each outpost in km (coordinates are integers between 0 and 10,000).

Output

For each case, output should consist of a single line giving the minimum D required to connect the network. Output should be specified to 2 decimal points.

Sample Input

1
2 4
0 100
0 300
0 600
150 750

Sample Output

212.13

大致題意:有n個衛星和m個哨所,現在要把m個哨所併入通信網絡,在n個哨所中安放衛星,安放有衛星的哨所互相通信可以無視距離,剩下的哨所需要配置信號接收器,信號接收器接收信號的半徑越大價格越高。每個哨所安放的信號接收器的型號都一樣,即信號接收半徑都一樣,求最低要購買接收信號半徑爲多少的信號接收器.

解題思路:用最小生成樹解,用最小生成樹求出聯通所有哨所的所有路徑長度,然後在裏面最長的路徑所聯通的哨所

裏放衛星。


1.普里姆算法:

#include <iostream>  // 普里姆算法
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
#define sc(a) scanf("%d",&a)
#define nsc(a,b) scanf("%d %d",&a,&b)
#define pr(a) printf("%d\n",a)
#define mem(a,x) memset(a,x,sizeof(a))
#define lf(i,l,r) for(int i=l;i<r;i++)
#define inf 0x3f3f3f3f
#define N 510

int t,n,m,cnt,x[N],y[N],vis[N];
double spot[N][N],num[N],dis[N];

void solve()
{
    int tol;
    cnt=0;
    lf(i,1,m+1)
    dis[i]=spot[1][i];
    vis[1]=1;
    lf(i,1,m)
    {
        tol=-1;
        num[cnt]=inf;  //用num數組來存儲最短路徑中的所有路徑。
        lf(j,1,m+1)
        {
            if(!vis[j]&&num[cnt]>dis[j])
            {
                num[cnt]=dis[j];
                tol=j;
            }
        }
        cnt++;
        if(tol==-1)
            return ;
        vis[tol]=1;
        lf(j,1,m+1)
        if(!vis[j])
            dis[j]=min(dis[j],spot[tol][j]);
    }
    return ;
}

int main()
{
    sc(t);
    while(t--)
    {
        nsc(n,m);
        lf(i,1,m+1)
        {
            vis[i]=0;
            nsc(x[i],y[i]);
            spot[i][i]=inf;
            lf(j,1,i)
            {
                spot[i][j]=spot[j][i]=sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
            }
        }
        solve();
        sort(num,num+cnt);  //排序,因爲衛星要放在裏面最長路徑連接的哨所
        printf("%.2lf\n",num[cnt-n]);  // 一共cnt-1條路徑,n-1條路徑可以通過放衛星替換
    }
    return 0;
}

2.克魯斯卡爾算法:

#include <iostream>  // 克魯斯卡爾算法
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
#define sc(a) scanf("%d",&a)
#define nsc(a,b) scanf("%d %d",&a,&b)
#define pr(a) printf("%d\n",a)
#define mem(a,x) memset(a,x,sizeof(a))
#define lf(i,l,r) for(int i=l;i<r;i++)
#define inf 0x3f3f3f3f
#define N 510

int t,n,m,cnt,x[N],y[N],p[N];
double num;
struct node
{
    int s;
    int e;
    double v;
} spot[N*N>>1];

int Find(int x)
{
    if(x!=p[x])
    {
        p[x]=Find(p[x]);
    }
    return p[x];
}

int cmp(node a,node b)
{
    return a.v<b.v;
}

void solve()
{
    int tol=0;
    num=0;
    lf(i,1,cnt)
    {
        int xx=Find(spot[i].s);
        int yy=Find(spot[i].e);
        if(xx!=yy)
        {
            p[xx]=yy;
            tol++;      //tol代表找到的是第幾條小的邊
            if(tol==m-n)  //第m-n條邊就是沒有替換的最後的一條邊。
            {
                num=spot[i].v;
                return ;
            }
        }
    }
    return ;
}

int main()
{
    sc(t);
    while(t--)
    {
        cnt=1;
        nsc(n,m);
        lf(i,1,m+1)
        {
            p[i]=i;
            nsc(x[i],y[i]);
            lf(j,1,i)
            {
                spot[cnt].s=i;
                spot[cnt].e=j;
                spot[cnt++].v=sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
            }
        } 
        sort(spot+1,spot+cnt,cmp);  //先排序。
        solve();
        printf("%.2lf\n",num);
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章