poj2349 Arctic Network ——最小生成树入门题_Prim算法

May 3, 2013
POJ Graph

题目链接:http://poj.org/problem?id=2349 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=914 题目大意:   有一些炮台,如果这个炮台有卫星接收器,那么任意两个有卫星接收器的炮台可以通信,不受距离限制;否者,两个炮台之间只能通过对讲机通信,这是受距离限制的。要买一种对讲机,用在需要的炮台上,要求所有炮台两两之间可以直接或者间接通信,问要买通信距离至少为多少的对讲机可以满足要求。输入:S卫星接收器的数量,P炮台的数量,然后是P行,每行代表一个炮台的坐标。输出要求的对讲机的通信距离D。 题目思路:   题目意思比较难懂。关键是satellite channel的安放方法,注意,它是放在炮台上的,只要这个炮台上有这货,它就可以和任何也有这货的炮台通信。明白这一点,然后就简单了。有S个卫星接收器,那么就可以减少S-1个距离开销。要让D尽可能小,就让这S-1个距离开销最大,所以,想法就是,求这些点的最小生成树,然后把所选的边排序,第S大的边的权值就是所求。   开始题意没搞懂。关键是“Any two outposts with a satellite channel can communicate via the satellite, regardless of their location.”这句话没有理解明白,也就是说,任何两个有卫星接收器的炮台都可通信!然后自己就把问题复杂化了……写的代码就很复杂了。。后来改了一下,就过了。。


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
typedef long long int LL;
const int MAXN =  0x3f3f3f3f;
const int  MIN =  -0x3f3f3f3f;
const double eps = 1e-9;
const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1},
  {1,1},{1,-1},{-1,-1}};
const int MAX  = 500+10;
int n, s, p;
double edge[MAX][MAX];
double lowcost[MAX];
int nearvex[MAX];

typedef struct Point {
  double x, y;
}Point;

typedef struct Vex {
  int i, j; double len;
  bool operator < (const Vex & other) const { // 不能写反了
    return len > other.len;
  }
}Vex;

map<int, bool> visit;
Vex vex[MAX];
Point point[MAX];

void prim(int u0) {
  int v;  // 尼玛定义类型错了,我去……
  int cur = 0, i, j;
  visit.clear();
  for (i = 1; i <= p; ++i) {
    lowcost[i] = edge[u0][i]; nearvex[i] = u0;
  }
  lowcost[u0] = 0; nearvex[u0] = -1;
  for (i = 1; i < p; ++i) {
    v = -1; double min = MAXN*1.0;
    for (j = 1; j <= p; ++j) {
      if (lowcost[j] < min && nearvex[j] != -1) {
        min = lowcost[j]; v = j;
      }
    }
    if (v != -1) {
      nearvex[v] = -1;
      vex[cur].i = v; vex[cur].j = nearvex[v]; vex[cur].len = lowcost[v];
      cur++;
      for (j = 1; j <= p; ++j) {
        if (lowcost[j] > edge[v][j] && nearvex[j] != -1) {
          lowcost[j] = edge[v][j]; nearvex[j] = v;
        }
      }
    }
  }
  sort(vex, vex + cur); 
  printf("%.2f\n", vex[s-1].len); 
}
int main(void){
#ifndef ONLINE_JUDGE
  freopen("poj2349.in", "r", stdin);
#endif
  scanf("%d", &n);
  int i, j;// k;
  while (n--) {
    scanf("%d%d", &s, &p);
    for (i = 1; i <= p; ++i) {
      scanf("%lf%lf", &point[i].x, &point[i].y);
    }
    for (i = 1; i <= p; ++i) {
      for (j = i + 1; j <= p; ++j) {
        double x1=point[i].x,y1 =point[i].y,x2 = point[j].x, y2=point[j].y;
        double dis = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
        edge[i][j] = edge[j][i] = dis;
      }
    }
    prim(1);
  }

  return 0;
}

  唉,好复杂的代码……题意理解最重要了,这种题目应该考的就是题意……   还有就是,结构体里面重载运算符的时候,貌似不能重载大于号?因为要逆序排序么,然后就把return改了一下。

comments powered by Disqus