In an episode of the Dick Van Dyke show, little Richie connects the freckles (on his Dad’s back )(to form a picture )(of the Liberty Bell.)
在DBDshow的剧情,小R连接这些点 在父亲的背上 to形成一个图片of 自由钟
Alas, one of the freckles turns out to be a scar, so his Ripley’s engagement falls through.
其中一个点变成了伤疤,所以他的 **(投入?) 失败了
Consider Dick’s back to be a plane with freckles at various (x,y) locations.
考虑D的后背 成一个平面,带着xy坐标
Your job is to tell Richie how to connect the dots so as to minimize the amount of ink used.
你的工作是告诉R 如何连接这些点,使用最少的墨水
Richie connects the dots by drawing straight lines between pairs, possibly lifting the pen between lines.
R连接这些点 通过两点直连, 可能在线之间抬笔(?)
When Richie is done there must be a sequence of connected lines from any freckle to any other freckle
当工作结束,必须一系列的线,任意两点连接好)
输入:
The first line contains 0 < n <= 100, the number of freckles on Dick’s back.
For each freckle, a line follows;
each following line contains two real numbers indicating the (x,y) coordinates of the freckle.
输出:
Your program prints a single real number to two decimal places: the minimum total length of ink lines that can connect all the freckles.
样例输入:
3
1.0 1.0
2.0 2.0
2.0 4.0
样例输出:
3.41
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <map>
#include <stack>
#include <iomanip>
using namespace std;
typedef struct Dot {
double x, y;
} Dot;
typedef struct Edge {
int u, v; // 起始坐标 结束坐标
double len; // 长度 距离
} Edge;
bool compare(Edge& a, Edge& b) {
return a.len <= b.len;
}
// ok
double getDistance(Dot& a,Dot& b) {
// a:(x1,y1) b:(x2,y2)
// (x2 - x1)^2 + (y2 - y1) ^2
// 开根号
double result = pow((b.x - a.x),2) + pow((b.y - a.y),2);
result = sqrt(result);
return result;
}
class UnionFind {
int father[101]; // 1 ~ 100 记录上级/老大
int contain[101]; // 包含多少小弟
int minIndex; // 范围
int maxIndex; // 范围
int cnt; //连通分量的个数
public :
UnionFind() {}
UnionFind(int minIndex, int maxIndex) {
// 1 ~ 4
this->minIndex = minIndex;
this->maxIndex = maxIndex;
this->cnt = maxIndex - minIndex + 1; // 连通分量的个数
for (int i = minIndex; i <= maxIndex ; i++) {
father[i] = -1;
contain[i] = 1;
}
}
int getRoot(int x) {
if (father[x] == -1) {
return x; // 自己就是老大
} else {
//自己不是老大,自己有上级
// 上级是set老大 还是 图上的父节点?
int d = father[x];
int root = getRoot(d);
if (d != root) {
father[x] = root; // 直接跟root算了,不跟图上的父节点
contain[d] -= contain[x]; // contain少了,投奔root了
}
return root;
}
}
bool isConnected(int x, int y) {
return getRoot(x) == getRoot(y);
}
bool connect(int x, int y) {
// cout << "目前正在连接" << x << " " << y << endl;
int xRoot = getRoot(x);
int yRoot = getRoot(y);
// cout << "根:" << xRoot << "and" << yRoot << endl;
if (xRoot == yRoot) {
return false; // 已经在同一个set里面了,已经在同一个连通分量里面了
} else {
// cout << x << " " << y << "可以连接" <<endl;
if(contain[x] >= contain[y]) {
// x 人多势大, y投奔x
father[yRoot] = xRoot;
contain[xRoot] += contain[yRoot];
} else {
// y人多势大,x投奔y
father[xRoot] = yRoot;
contain[yRoot] += contain[xRoot];
}
}
cnt --; //连通分量少1
}
int getCnt() {
return cnt;
}
void show() {
cout << "---目前情况---" << endl;
cout << "father :";
for (int i = minIndex; i <= maxIndex; i++) {
cout << setw(4) << father[i] << "\t";
}
cout << endl;
cout << "index :";
for (int i = minIndex; i <= maxIndex; i++) {
cout << setw(4) << i << "\t";
}
cout << endl << endl;
cout << "contain :";
for (int i = minIndex; i <= maxIndex; i++) {
cout << setw(4) << contain[i] << "\t";
}
cout << endl;
cout << "index :";
for (int i = minIndex; i <= maxIndex; i++) {
cout << setw(4) << i << "\t";
}
cout << endl;
cout << "---打印完毕---" << endl << endl;
}
void print(vector<Edge> edges) {
cout << "目前edges的vector:" << endl;
for (int i = 0; i <= edges.size() - 1; i++) {
cout << edges[i].u << " " << edges[i].v << " " << edges[i].len << endl;
}
cout << "**打印完毕" << endl;
}
double mst(vector<Edge> edges) {
double sum = 0;
sort(edges.begin(), edges.end(), compare);
// print(edges);
for (int i = 0; i <= edges.size() - 1; i++) {
int u = edges[i].u;
int v = edges[i].v;
bool flag = connect(u, v);
// cout << "***" << sum << endl;
if (flag) {
sum += edges[i].len;
// cout << "***" << sum << endl;
if (getCnt() == 1) {
return sum;
}
} else {
// cout << "***" << "no!" << endl;
continue;
}
}
return -1;
}
};
int main() {
int n;
while (cin >> n && n != 0) {
if (n == 1) {
cout << "0" << endl;
} else {
vector<Dot> dots;
vector<Edge> edges;
UnionFind uf(0,n-1); // 一共有n个点,编号: 0 ~ n-1
Dot dot;
for (int i = 0; i <= n - 1; i ++) {
cin >> dot.x >> dot.y;
dots.push_back(dot); // dots[0] 就是 0点 // 找具体的点的x、y 就找dots[i].x y
}
Edge edge;
for (int i = 0; i <= dots.size() - 1; i++) {
for (int j = i + 1; j <= dots.size() - 1; j++) {
edge.u = i;
edge.u = j; // 0点到1点
edge.len = getDistance(dots[i],dots[j]);
edges.push_back(edge);
}
}
double sum = uf.mst(edges);
printf("%.2f",sum);
}
}
return 0;
}