Freckles

2013-06-03 Robert Zhang 更多博文 » 博客 » GitHub »

原文链接 http://huiming.io/2013/06/03/freckles.html
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


分析:在坐标点构成的图上应用最小生成树算法即可。注意几点:

1)边权是动态计算出来的

2)每对坐标之间都可以有一条边

3)由于图的顶点不再由整数标识,因此用map代替典型算法中的vector

<!--more-->

#include <iostream>
#include <vector>
#include <map>
#include <limits>
#include <cmath>
#include <cstdio>

using namespace std;

class Point {
public:
  Point() : x(0), y(0) {}

  Point(double ax, double ay) : x(ax), y(ay) {}

  bool operator <(const Point & p) const {
    bool r;
    if (x < p.x)
      r = true;
    else if (x > p.x)
      r = false;
    else {
      if (y < p.y)
        r = true;
      else
        r = false;
    }
    return r;
  }

  double distance(const Point & p) const {
    double dx = x - p.x;
    double dy = y - p.y;
    return sqrt(dx * dx + dy * dy);
  }

  double x;
  double y;
};

typedef vector<Point> Graph;

double mst(const Graph & g) {
  double r = 0;
  map<Point, bool> intree;
  map<Point, double> dist;
  map<Point, Point> pred;
  for (int i = 0; i < g.size(); i++) {
    dist[g[i]] = numeric_limits<double>::max();
  }
  const Point * p = &g[0];
  while (p) {
    intree[*p] = true;
    const Point * np = 0;
    double min = numeric_limits<double>::max();
    map<Point, double>::iterator it = dist.begin();
    for (; it != dist.end(); it++) {
      const Point & p2 = it->first;
      //use find to avoid adding p2 to intree if not yet
      if (intree.find(p2) == intree.end()) {
        double d = p->distance(p2);
        if (d < it->second) {
          it->second = d;
          pred[p2] = *p;
        }
        if (it->second < min) {
          min = it->second;
          np = &p2; //It doesn't matter np(then passed to p) points to inside of dist rather than g
        }
      }
    }
    p = np;
  }
  map<Point, Point>::iterator it = pred.begin();
  for (; it != pred.end(); it++) {
    r += it->first.distance(it->second);
  }
  return r;
}

int main() {
  int n = 0;
  cin >> n;
  for (int i = 0; i < n; i++) {
    Graph g;
    int nv = 0;
    cin >> nv;
    for (int j = 0; j < nv; j++) {
      double x, y;
      cin >> x >> y;
      g.push_back(Point(x, y));
    }
    if (i) {
      printf("n");
    }
    printf("%0.2fn", mst(g));
  }
  return 0;
}