昨天下午做到现在,差点做吐。。。
本题需要注意,C == 0、1的特殊情况,中间算边长度时用int,最后用double转化(否则超时),再次中间变量的值要细心,否则弄错。
不过最坑的还是,我在边转化成int后,范围忘了改变。。。结果还以为别的地方出了问题,贡献N WA。。。。。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
const int N = 5005;
int pre0[N];
int num;
double sum;
struct edges
{
int pre;
int suc;
int wei;
}edge[N];
struct point
{
int x;
int y;
}poi[101];
int cmp(edges x, edges y)
{
return (x.wei < y.wei) ? 1 : 0;
}
void init(int vs)
{
for(int i = 1; i <= vs; i ++)
pre0[i] = i;
}
int findd(int x)
{
int r = x;
while(r != pre0[r])
r = pre0[r];
return r;
}
void Union(int x, int y, int z)
{
int f1, f2;
f1 = findd(x);
f2 = findd(y);
// printf("fuck\n");
if(f1 != f2)
{
pre0[f2] = f1;
num ++;
sum += sqrt(z);
}
}
double kruskal(int es, int vs)
{
num = 1;
sum = 0;
init(vs);
sort(edge, edge + es, cmp);
for(int i = 1; i < es; i ++)
Union(edge[i].pre, edge[i].suc, edge[i].wei);
// printf("%d %d %d %lf ", num, vs, es, sum);
if(num == vs) return sum;
else return -1;
}
int main()
{
// freopen("in.txt", "r", stdin);
int T, C, m;
__int64 w;
double ans;
scanf("%d", &T);
while(T --)
{
scanf("%d", &C);
for(int i = 1; i <= C; i ++)
scanf("%d%d", &poi[i].x, &poi[i].y);
if(C == 0 || C == 1) { printf("0.0\n"); continue; }
int num0 = 1;
for(int i = 1; i <= C - 1; i ++)
for(int j = i + 1; j <= C; j ++)
{
w = (poi[j].x - poi[i].x) * (poi[j].x - poi[i].x) + (poi[j].y - poi[i].y) * (poi[j].y - poi[i].y);
// printf("%d\n", w);
if(w >= 100 && w <= 1000000)
{
edge[num0].pre = i;
edge[num0].suc = j;
edge[num0].wei = w;
// printf("%lf\n", edge[num0].wei);
num0 ++;
}
}
ans = kruskal(num0, C);
if(ans < 0) printf("oh!\n");
else printf("%.1lf\n", ans * 100);
}
return 0;
}