#UVa:10034-Freckles

灆洢 2015-03-15 11:57:03

建立最小生成樹(Minimum Spanning Tree, MST)並算出樹上之權重(也就是兩點之間的距離)的總和即可得解。

C++(0.009)

/*******************************************************/
/* UVa 10034 Freckles                                  */
/* Author: Maplewing [at] knightzone.studio            */
/* Version: 2015/03/15                                 */
/*******************************************************/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;

struct Point{
  int group;
  double x;
  double y;
};

struct Line{
  int aPointIndex, bPointIndex;
  double length;
};

bool compareByLength(const Line &a, const Line &b){
  return a.length < b.length;
}

double pointDistance(const Point &a, const Point &b){
  double deltaX = a.x - b.x, deltaY = a.y - b.y;
  return sqrt(deltaX * deltaX + deltaY * deltaY);
}

bool isBuildMSTFinished(const Point points[], int n){
  for( int i = 0 ; i < n-1 ; ++i ){
    if( points[i].group != points[i+1].group ){
      return false;
    }
  }
  return true;
}

void putInSameGroup(Point points[], int n, int group1, int group2){
  int minGroup = min(group1, group2);
  for( int i = 0 ; i < n ; ++i ){
    if( points[i].group == group1 || points[i].group == group2 ){
      points[i].group = minGroup;
    }
  }
}

int main(){
  int testcase;
  while( scanf("%d", &testcase) != EOF ){
    for( int caseCount = 0 ; caseCount < testcase ; ++caseCount ){
      if( caseCount > 0 ) printf("\n");

      int n;
      scanf("%d", &n);

      Point points[105];
      for( int i = 0 ; i < n ; ++i ){
        scanf("%lf%lf", &(points[i].x), &(points[i].y));
        points[i].group = i;
      }

      vector<Line> lines;
      for( int i = 0 ; i < n ; ++i ){
        for( int j = i + 1 ; j < n ; ++j ){
          Line l;
          l.aPointIndex = i;
          l.bPointIndex = j;
          l.length = pointDistance(points[i],points[j]);
          lines.push_back(l);
        }
      }

      sort( lines.begin(), lines.end(), compareByLength);

      double pathLengthSum = 0;
      for( int i = 0 ; !isBuildMSTFinished(points, n) ; ++i ){
        if( points[lines[i].aPointIndex].group == points[lines[i].bPointIndex].group ){
          continue;
        }
        pathLengthSum += lines[i].length;
        putInSameGroup(points, n, points[lines[i].aPointIndex].group, points[lines[i].bPointIndex].group);
      }

      printf("%.2lf\n", pathLengthSum);
    }
  }
  return 0;
}

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料