题目链接:http://poj.org/problem?id=2349
求最小生成树中第S大的边,结点给的是坐标(坑爹啊)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 500
struct edge
{
int u, v;
double w;
}e[250000];
struct data
{
int x, y;
}a[N];
int S, P, tot, cnt, p[N];
double dis(data a, data b)
{
int x = a.x - b.x;
int y = a.y - b.y;
double xx = x * x;
double yy = y * y;
return sqrt(xx + yy);
}
int find(int x)
{
return p[x] != x ? p[x] = find(p[x]) : x;
}
void add(int x, int y, double z)
{
tot++;
e[tot].u = x;
e[tot].v = y;
e[tot].w = z;
}
double cmp(double a, double b)
{
return a > b;
}
double cmp2(edge a, edge b)
{
return a.w < b.w;
}
int main()
{
int r1, r2, t;
double ans, w[250000];
cin >> t;
while (t--)
{
cin >> S >> P;
for (int i = 0; i < P; i++) p[i] = i;
tot = ans = cnt = 0;
memset(e, 0, sizeof(e));
memset(w, 0, sizeof(w));
for (int i = 0; i < P; i++) scanf("%d%d", &a[i].x, &a[i].y);
for (int i = 0; i < P; i++)
for (int j = 0; j < P; j++)
{
if (i != j) add(i, j, dis(a[i], a[j]));
}
sort(e + 1, e + 1 + tot, cmp2);
for (int i = 0; i < tot; i++)
{
r1 = find(e[i].u); r2 = find(e[i].v);
if (r1 != r2)
{
p[r2] = r1; w[cnt++] = e[i].w;
}
}
sort(w, w + cnt, cmp);
if (S == 0) ans = w[0];
else ans = w[S - 1];
printf("%.2lf\n", ans);
}
return 0;
}