poj 2349 Arctic Network(最小生成树变形)

来源:互联网 发布:网络设备监控软件 开源 编辑:程序博客网 时间:2024/06/06 05:12
Arctic Network
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 15862 Accepted: 5051

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

12 40 1000 3000 600150 750

Sample Output

212.13


题意:在北极有n个站点,现在有s个卫星系统,一个卫星系统可以设置在一个站点,有卫星的站点之间通信不需要耗费任何东西,如果两个站点之间有一个没有卫星,则需要花费两者的距离的花费D,现在问你,要做到所有站点都能互相通信,且所有花费D都相等(即取最大的那一个),D最小是多少?

思路:刚看到这道题,没什么思路。 度娘了一下也没怎么看懂,最后自己推了一下。

这道题一看就是求最小生成树,可是有s个卫星系统怎么处理呢?在0个或者1个卫星的情况下(1个无法起到作用,跟0个一样),这个题目就是求最小生成树,然后取最大的边。那么在一个卫星的基础上,我们每添加一个卫星,就相当于删除了两个村庄之间的一条边(由于卫星可以随便放置,所以我们可以假设两个卫星就在当前最大边的两个村庄),然后两个村庄合为一个村庄,由于我们要求最小的D,故我们要删除的肯定是当前最小生成树里最大的那一条边。以此类推,题目要求的其实是最小生成树里的第s大边。

这里有个疑问,比如当前s=3,最小生成树最长边与次长边的两边结点没有重合的,那么我们用两个卫星找到最长边的时候,是不是能用一个卫星就删除次长边呢? 答案是肯定的。

我们每一次加一个卫星,就是删除一条边,删除一条边,就是把最小生成树分割出一个分量(最小生成树是无环的,这个结论是显而易见的),那么,无论何时,当前的最长边所在的那一个连通分量,有且仅有一个卫星。我们只需要把那个卫星与当前最长边的其中一个结点连接,自然就能删除最长边了。 如果看不懂可以画个图看看,应该是很容易懂的。

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;#define N 510#define INF 100000000int k,n;struct Point{    double x,y;} p[N];double ma[N][N],ans[N],d[N];int flag[N];double dis(Point a,Point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}bool cmp(double a,double b){    return a>b;}void prim(){    for(int i=1; i<n; i++)        d[i]=ma[0][i];    flag[0]=1;    for(int i=1; i<n; i++)    {        double maxn=INF;        int v=-1;        for(int j=1; j<n; j++)            if(!flag[j]&&maxn>d[j])            {                maxn=d[j];                v=j;            }        ans[i-1]=maxn;        flag[v]=1;        for(int j=1;j<n;j++)            if(!flag[j]&&d[j]>ma[v][j])                d[j]=ma[v][j];    }}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d %d",&k,&n);        for(int i=0; i<n; i++)            scanf("%lf %lf",&p[i].x,&p[i].y);        for(int i=0; i<n; i++)            for(int j=0; j<n; j++)                ma[i][j]=dis(p[i],p[j]);        memset(flag,0,sizeof(flag));        prim();        sort(ans,ans+n-1,cmp);        if(k==0) k=1;        printf("%.2lf\n",ans[k-1]);    }    return 0;}


0 0