最小生成树的变形
最小生成树只能有n-1条边。
所以我们有无线资源的时候,为了尽量发挥这些昂贵资源的价值,我们把这些资源用到最小生成树的最长的s个边上。
即,求最小生成树的第p-s个边
#include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; #define N 500 #define M 200000 int n, m, t, dot[N][2]; int v[M], u[M], r[M], p[M]; double w[M]; void init() { int dx, dy; scanf("%d%d",&t,&n); for(int i = 0; i < n; i++) scanf("%d%d",&dot[i][0],&dot[i][1]); m = 0; for(int i = 0; i < n; i++) for(int j = i+1; j < n; j++) { dx = dot[i][0]-dot[j][0]; dy = dot[i][1]-dot[j][1]; w[m] = sqrt(dx*dx+dy*dy); u[m] = i; v[m] = j; m++; } } int cmp(const int i, const int j) { return w[i]<w[j]; } int find(int x) { return p[x]==x?x:p[x] = find(p[x]); } double kruskal() { int cnt = 0; for(int i = 0; i < n; i++) p[i] = i; for(int i = 0; i < m; i++) r[i] = i; sort(r,r+m,cmp); for(int i = 0; i < m; i++) { int e = r[i]; int x = find(u[e]); int y = find(v[e]); if(x!=y) { if(++cnt==n-t) return w[e]; p[x] = y; } } return 0.0; } int main () { int cas; scanf("%d",&cas); while(cas--) { init(); printf("%.2lf\n",kruskal()); } return 0; }