解题思路:
依旧是最小生成树,如果边长小于10或大于1000就跳过,最后看生成树是不是有N - 1条边。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <stack>
#define LL long long
#define FOR(i,x,y) for(int i=x;i<=y;i++)
#define rFOR(i,x,y) for(int i=x;i>=y;i--)
using namespace std;
const int maxn = 100 + 10;
struct Point
{
double x , y;
}P[maxn];
int N , M;
double get_dis(const Point& A , const Point& B)
{
double x = A.x - B.x;
double y = A.y - B.y;
return sqrt(x * x + y * y);
}
struct Edge
{
int u;
int v;
double w;
bool operator < (const Edge& rhs) const
{
return w < rhs.w;
}
}e[maxn * maxn];
int f[maxn];
int find(int x)
{
return f[x] == x ? x : f[x] = find(f[x]);
}
void Kruskal()
{
sort(e , e + M);
FOR(i,1,N) f[i] = i;
double ans = 0 ; int n = 0;
for(int i = 0 ; i < M ; i ++)
{
if(e[i].w < 10 || e[i].w > 1000) continue;
int x = find(e[i].u);
int y = find(e[i].v);
if(x != y)
{
f[x] = y;
ans += e[i].w;
n++;
}
}
if(n == N-1) printf("%.1lf\n",ans*100);
else printf("oh!\n");
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&N);M = 0;
FOR(i,1,N) scanf("%lf%lf",&P[i].x , &P[i].y);
FOR(i,1,N)
{
FOR(j,i+1,N)
{
double dis = get_dis(P[i] , P[j]);
e[M].u = i;
e[M].v = j;
e[M++].w = dis;
}
}
//for(int i=0;i<M;i++) cout<<e[i].u<<' '<<e[i].v<<' '<<e[i].w<<endl;
Kruskal();
}
return 0;
}