PC/UVa:111001/10034
虽说是浮点数的题目,但是也做了。
这道题就是求最小生成树,使用书中介绍的Prim算法,将点依次加入到最小生成树中。
根据书上的算法,保存每一个树外节点到最小生成树内节点的最短距离。每次从该最小距离中选择一个点加入最小生成树。如果剩余点到这个点的距离小于已有的值,则更新。
首先在最小生成树中加入点0
,初始化距离数组为其余各点到点0
的范围。
#include <iostream>
#include <vector>
#include <iomanip>
#include <climits>
#include <cmath>
#define EPS 1e-6
using namespace std;
void calDistance(vector<vector<double>> &Graph, const vector<pair<double, double>> &vdPoint)
{
double distance, deltaX, deltaY;
for (size_t i = 0; i < vdPoint.size(); i++)
{
for (size_t j = i + 1; j < vdPoint.size(); j++)
{
deltaX = vdPoint[i].first - vdPoint[j].first;
deltaY = vdPoint[i].second - vdPoint[j].second;
distance = deltaX * deltaX + deltaY * deltaY;
Graph[i][j] = distance;
Graph[j][i] = distance;
}
}
}
void minSpanningTree(const vector<vector<double>> &Graph)
{
//Prime算法
//根据书上的实现,保存每一个树外节点到最小生成树内节点的最短距离
//每次从该最小距离中选择一个点加入最小生成树
//如果剩余点到这个点的距离小于已有的值,则更新
//首先加入点0,距离数组为到点0的范围
vector<double> vdWeight;
vector<bool> vbInTree(Graph.size(), false);
vbInTree[0] = true;
vector<double> vdMinDistance(Graph.size(), 0.0);
for (size_t out = 1; out < Graph.size(); out++)
{
vdMinDistance[out] = Graph[0][out];
}
while (1){
//查找最小值
double min;
size_t out = 0, idx = 0;
for (; out < Graph.size(); out++)
{
if (!vbInTree[out]){
min = vdMinDistance[out];
idx = out;
break;
}
}
for (; out < Graph.size(); out++)
{
if (!vbInTree[out]){
if (min - vdMinDistance[out] > EPS){
min = vdMinDistance[out];
idx = out;
}
}
}
if (idx == 0) break;
//加入该点
vbInTree[idx] = true;
vdWeight.push_back(min);
//更新
for (size_t out = 0; out < Graph.size(); out++)
{
if (!vbInTree[out]){
if (vdMinDistance[out] - Graph[idx][out] > EPS){
vdMinDistance[out] = Graph[idx][out];
}
}
}
}
double min = 0.0;
for (size_t i = 0; i < vdWeight.size(); i++)
{
min += sqrt(vdWeight[i]);
}
cout << setprecision(2) << fixed << min << endl;
}
int main()
{
int T = 0;
cin >> T;
for (int t = 0; t < T; t++)
{
int N = 0;
cin >> N;
vector<pair<double, double>> vdPoint;
for (int n = 0; n < N; n++)
{
double x, y;
cin >> x >> y;
vdPoint.push_back(pair<double, double>(x, y));
}
vector<vector<double>> Graph(N, vector<double>(N, 0.0));
calDistance(Graph, vdPoint);
minSpanningTree(Graph);
if (t != T - 1) cout << endl;
}
return 0;
}
/*
1
3
1.0 1.0
2.0 2.0
2.0 4.0
*/