这题就是用最少的路径,使得图有S个连通分量。再求这些路径中的最大值。
用Kruskal算法,在刚好有S个连通分量时终止运算就行了。
double max(double a,double b) {return a>b?a:b;} //outpost struct outpost{ int x,y; outpost():x(0),y(0){} void init(int x,int y){ this->x=x;this->y=y; } int operator*(const outpost&b)const{ return (x-b.x)*(x-b.x)+(y-b.y)*(y-b.y); } }I[500]; int In; //边 struct edge{ int from,to; double value; void init(int from,int to,double value){ this->from=from;this->to=to;this->value=value; } bool operator <(const edge&b)const{ return value<b.value; } }edges[125000]; int En; //并查 struct node{ int parent; void init(int i){ parent=i; } }nodes[500]; int find(int x){ int r=x; while(r!=nodes[r].parent){ r=nodes[r].parent; } return nodes[x].parent=r; } int main(void) { int T;cin>>T; while(T--){ int S,C,x,y; scanf("%d%d",&S,&C);In=0; //存outpost位置 for(int i=0;i<C;i++){ scanf("%d%d",&x,&y); I[In++].init(x,y); } //建边 En=0; for(int i=0;i<C;i++){ for(int j=i+1;j<C;j++){ int D2=I[i]*I[j]; edges[En++].init(i,j,sqrt((double)D2)); } } //排序 sort(edges,edges+En); double ANS=0; //计算 for(int i=0;i<C;i++){//并查集初始化 nodes[i].init(i); } int NNN=C;//NNN代表有几个连通分量 for(int i=0;i<En;i++){ if(NNN==S) break;//恰好有S个连通分量时结束 static int a,b; a=find(edges[i].from),b=find(edges[i].to); if(a==b) continue; NNN--; nodes[a].parent=b; ANS=max(ANS,edges[i].value); } printf("%.2f\n",ANS); } return 0; }