传送门 思路:给你坐标点,让你求一条经过每个点的最短路径。
题意:最小生成树做即可。注意特判条件和位置。应放在kru中。
const int maxn = 1e6 + 5;
using namespace std;
struct node {
double u, v;
double w;
} e[maxn];
int p[maxn];
bool cmp(node x, node y) {
return x.w < y.w;
}
int find(int x) { ///并查集压缩路径//加边法
///return p[x]==x?x:find(p[x]);
int r = x;
while(r != p[r])
r = p[r];
int i = x, j;
while(i != r) {
j = p[i];
p[i] = r;
i = j;
}
return r;
}
double x[maxn], y[maxn];
int main() {
int m;
int T;
while(cin >> T) {
while(T--) {
int n;
cin >> n;
for(int i = 1; i <= n; i++)
p[i] = i;
for(int i = 1; i <= n; i++) {
cin >> x[i] >> y[i];
}
int flag = 0;
int cnt = 0;
for(int i = 1; i <= n; i++)
for(int j = i + 1; j <= n; j++) {
++cnt;
e[cnt].u = i;
e[cnt].v = j;
e[cnt].w = sqrt(1.0 * (x[i] - x[j]) * (x[i] - x[j]) + 1.0 * (y[i] - y[j]) * (y[i] - y[j]));
}
double cost = 0.0;
sort(e + 1, e + cnt + 1, cmp);
for(int i = 1; i <= cnt; i++) {
int x = find(e[i].u);
int y = find(e[i].v);
if(x == y)
continue;
if(e[i].w<10||e[i].w>1000)
continue;
cost += e[i].w * 100;
p[x] = y;
flag++;
}
if(flag == n-1)
printf("%.1lf\n", cost);
else cout << "oh!" << endl;
}
}
return 0;
}