我的算法是,先生成最小生成树,在从树中最长边开始,贪心删除边。最后没有删除的边的最大值就是答案。 感觉思路正确,不知道问题出在哪里,下面是代码,60分,最后两个WA。 求求佬们捞我一把。
//P1991 无线通讯网
//先用最小生成树建树,在贪心舍弃树边
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>
#define ll long long
using namespace std;
const int P=501;
struct node{
int x,y;
int put;
}poi[P];
struct edge{
int from,to;
double w;
int check;//值为1 表示加入了最小生成树中
}e[P*P];
int s,p,totedge=0,f[P],k=0;
double maxl=0;
double dist(int x1,int y1,int x2,int y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
bool cmp1(edge a,edge b){
return a.w<b.w;
}
bool cmp2(edge a,edge b){
if(a.check!=b.check)return a.check>b.check;
else return a.w<b.w;
}
int find(int x){
return x==f[x]?x:f[x]=find(f[x]);
}
double Max(double a,double b){
return a>b?a:b;
}
int main()
{
scanf("%d%d",&s,&p);
for(int i=1;i<=p;i++){
scanf("%d%d",&poi[i].x,&poi[i].y);
f[i]=i;
}
for(int i=1;i<=p;i++){
for(int j=i+1;j<=p;j++){
e[++totedge].from=i;
e[totedge].to=j;
e[totedge].w=dist(poi[i].x,poi[i].y,poi[j].x,poi[j].y);
}
}
sort(e+1,e+1+totedge,cmp1);//第一遍排序,建树
for(int i=1;i<=totedge;i++){
int a=e[i].from,b=e[i].to;
double w=e[i].w;
if(find(a)==find(b))continue;
f[find(a)]=find(b);
k++;
e[i].check=1;//加上了该边到树中
if(k==p-1)break;
}
sort(e+1,e+1+totedge,cmp2);//第二遍排序,把树中边,按从小到大排到前面
//开始删树边
//贪心删,总是先删除树中最大的边
for(int i=k;i>=1;i--){
if(s==0)break;
int a=e[i].from,b=e[i].to;
double w=e[i].w;
if(poi[a].put==0 and s>0){
poi[a].put=1;
s--;
}
if(poi[b].put==0 and s>0){
poi[b].put=1;
s--;
}
if(poi[b].put==1 and poi[a].put==1){
e[i].check=0;//删边
}
}
for(int i=1;i<=k;i++){
if(e[i].check==1)
maxl=Max(maxl,e[i].w);
}
if(maxl==0)printf("0");//不知道结果输出0.00 算不算错,所以特判一下
else printf("%.2lf",maxl);
return 0;
}