POJ 2349 Arctic Network 最小生成树

来源:互联网 发布:郑州淘宝加盟 编辑:程序博客网 时间:2024/06/10 10:46

POJ 2349 Arctic Network 最小生成树

Arctic Network POJ - 2349

  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 Input12 40 1000 3000 600150 750
Sample Output212.13

  题目大意:有s个通信工具和p个点,有通信工具的任意两个点之间可以相互连通;否则,每个点只能和距离小于等于d的点进行连通。给出s和p个点的坐标,求d的最小值。

  直接用最小生成树解决即可,在数组d中记录下在形成最小生成树的过程中单次连接所需要的权值,显然,d中记录的数据一定是从小到大排开,所以,d的最小值一定是用s个通信工具省略去s-1条最大边之后的最大边。

  即,每次完成记录后输出d[(p-1)-(s-1)-1] = d[p-s-1]即可。

  这道题刚开始WA了很多遍,最后找来找去出现在并查集的初始化部分。WA的初始代码写的是:
for(int i=0 ; i<p ; i++) pre[i]=i,height[i]=1;

  当时觉得以为只用将初始化上限定为边集的数量就可以了,结果后来才突然反应过来并查集的作用对象是点集,又一个小白经验get。

  AC代码:

////  main.cpp//  L////  Created by LucienShui on 2017/5/11.//  Copyright © 2017年 LucienShui. All rights reserved.//#include <iostream>#include <algorithm>#include <set>#include <string>#include <vector>#include <queue>#include <map>#include <cstdio>#include <cmath>#include <cstring>#define memset(a,b) memset(a,b,sizeof(a))using namespace std;const int maxn = 500+7;int s,p,pre[maxn],height[maxn],cnt,num;//cnt是边集的数量,num是d数组中元素下标double d[maxn];struct {//记录点    int x,y;}node[maxn];struct Edge{//记录边    int b,e;    double val;    bool operator < (const Edge x) const {        return this->val < x.val;    }}edge[maxn*maxn];int Find(int x) {//while以及附帶路徑壓縮的版本,遞歸在數據量比較大的時候可能爆    if(x==pre[x]) return x;    int p=x,q;    while(x!=pre[x]) x=pre[x];    while(p!=pre[p]) {        q=pre[p];        pre[p]=x;        p=q;    }    return x;}void Add(int i, int j) {    int x=Find(i),y=Find(j);    if(x==y) return ;    if(height[x]<height[y]) pre[x]=y;    else {        if(height[x]==height[y]) height[x]++;        pre[y]=x;    }    return ;}double kruskal() {    sort(edge,edge+cnt);    num = 0;    for(int i=0 ; i<p ; i++) pre[i]=i,height[i]=1;//并查集初始化    for(int i=0 ; i<cnt ; i++) {        if(Find(edge[i].b)!=Find(edge[i].e)) {            Add(edge[i].b,edge[i].e);            d[num++] = edge[i].val;//记录当前边的权值        }    }    return d[p-s-1];//最终结果}double calc(int a, int b) {    int x = node[a].x - node[b].x,y = node[a].y - node[b].y;    return sqrt(x*x+y*y);}void solve() {    cnt = 0;    scanf("%d%d",&s,&p);    for(int i=0 ; i<p ; i++) {        scanf("%d%d",&node[i].x,&node[i].y);    }    for(int i=0 ; i<p-1 ; i++) {        for(int j=i+1 ; j<p ; j++) {            edge[cnt].b = i;            edge[cnt].e = j;            edge[cnt++].val = calc(i,j);        }    }    printf("%.2f\n",kruskal());}int main() {#ifndef ONLINE_JUDGE    freopen("in.txt", "r", stdin);#endif    int t;    scanf("%d",&t);    while(t--) {        solve();    }    return 0;}
原创粉丝点击