P1991 无线通讯网,关于算法的疑问
查看原帖
P1991 无线通讯网,关于算法的疑问
391638
AUTOM楼主2020/11/24 11:26

我的算法是,先生成最小生成树,在从树中最长边开始,贪心删除边。最后没有删除的边的最大值就是答案。 感觉思路正确,不知道问题出在哪里,下面是代码,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;
}
2020/11/24 11:26
加载中...