先计算出最小生成树,然后在输出第p-s小的边
#include<stdio.h> #include<stdlib.h> #include<math.h> #include<string.h> #define N 501 #define Maxint 9999999 double c[N][N],x[N],y[N],dist[N]; int s[N], closest[N],n; int cmp(const void *a,const void *b) { return *(double *)a > *(double *)b ? 1 : -1; } void Prim(int v) { int i,j,k; double min,lowcost[N]; s[v] = 1; for(i=1; i<n; i++) { lowcost[i] = c[v][i]; closest[i] = v; s[i] = 0; } for(i=1; i<n; i++) { min = Maxint; j = 1; for(k=1; k<n; k++) { if((lowcost[k]<min)&&(!s[k])) { min = lowcost[k]; j = k; } } s[j] = 1; lowcost[j] = min; dist[i-1] = min;//存放最小生成树的值,将每个最小的边都存起来 for(k = 0; k<n; k++) { if((c[j][k]<lowcost[k])&&(!s[k])) { lowcost[k] = c[j][k]; closest[k] = j; } } } } int main() { int i,j,m,ncases; scanf("%d",&ncases); while( ncases-- ) { scanf("%d%d",&m,&n); for(i=0; i<n; i++) { scanf("%lf%lf",&x[i],&y[i]); for(j=0; j<=i; j++) { c[i][j] = sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); c[j][i] = c[i][j]; } } Prim(0); qsort(dist,n-1,sizeof(dist[0]),cmp); printf("%.2lf\n",dist[n-m-1]); } return 0; }
然后我用Kruskal 做了一遍,既然只要输出第 p-s 小的边,那么我可以不用生成树,即用并查集的方式直接找出第p-s小的边然后输出即可,但是WA的好多次,于是我就随机生成数据,然后用上面正确的代码生成正确的数据和 Kruskal 代码出来的结果对比,最后发现_index写在里面出去的值就自动变为0 了,太尼玛。。。。无语了。
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define NLEN 10000 #define ELEN 500000 typedef struct Edge { int u, v; double w; }Edge; Edge e[ELEN]; typedef struct Point { int x, y; }Point; Point point[NLEN]; int p[NLEN]; void init(int n) { for(int i = 0; i < n; i++) { p[i] = i; } } double dis(int i, int j) { int xx = abs(point[i].x - point[j].x); int yy = abs(point[i].y - point[j].y); double ans = sqrt(xx*xx + yy*yy); return ans; } bool cmp(Edge a, Edge b) { return a.w < b.w; } int find(int x) { return p[x] == x ? x : (p[x] = find(p[x])); } double kruskal(int num, int s) { int m = 0; for(int i = 0; i < num; i++) { int t1 = find(e[i].u); int t2 = find(e[i].v); if(t1 != t2) { p[t1] = t2; m++; } if(m == s) { return e[i].w; } } } int main() { int t; int s, p; // FILE* fp = freopen("out_main", "w", stdout); // freopen("in", "r", stdin); scanf("%d", &t); while(t--) { int _index = 0; scanf("%d%d", &s, &p); for(int i = 0; i < p; i++) { scanf("%d%d", &point[i].x, &point[i].y); } for(int i = 0; i < p; i++) { for(int j = i+1; j < p; j++) { e[_index].u = i; e[_index].v = j; e[_index++].w = dis(i, j); } } init(p); sort(e, e+_index, cmp); // for(int i = 0; i < _index; i++) { // printf("%.2lf ", e[i].w); // } // printf("\n"); double ans = kruskal(_index, p-s); printf("%.2lf\n", ans); // fprintf(fp, "%.2lf\n", ans); } // fclose(fp); // fclose(stdout); // fclose(stdin); return 0; }
这里顺便贴上随机数生成的代码吧:
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <stdlib.h> using namespace std; #define TESTS 10 #define random(x) (rand()%x) int main() { FILE *fp; int t = TESTS; fp = freopen("in", "w", stdin); fprintf(fp, "%d\n", t); for(int i = 0; i < TESTS; i++) { int p = random(10); int s = random(p); fprintf(fp, "%d %d\n", s, p); for(int j = 0; j < p; j++) { int x = random(10000); int y = random(10000); fprintf(fp, "%d %d\n", x, y); } } return 0; }