专栏文章

P1991 无线通讯网 最小生成树

个人记录参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miqav4xi
此快照首次捕获于
2025/12/04 01:47
3 个月前
此快照最后确认于
2025/12/04 01:47
3 个月前
查看原文
这道题的关键在于如何用卫星电话去替换掉最小生成树上的最大边
先是以为两个电话组组成单一的一条边
60pts:
CPP
#include<bits/stdc++.h>
using namespace std;
const int N=505;
const int Max=20000;
struct Node{
	int x,y;
}node[N];
double dis[N],ans[N];
int in[N],n,Q;
double Dis(int a,int b){
	return sqrt((node[a].y-node[b].y)*(node[a].y-node[b].y)+
				(node[a].x-node[b].x)*(node[a].x-node[b].x));
}
double Min(double a,double b){return a<b?a:b;}
bool cmp(double a,double b){return a>b;}
int main(){
	cin>>Q>>n;
	for(int i=1;i<=n;i++){
		cin>>node[i].x>>node[i].y;
		dis[i]=Max;
	}
	int m=Max,u,v;
	dis[1]=0;
	for(int i=1;i<=n;i++){
		m=Max;
		for(int j=1;j<=n;j++)
			if(dis[j]<m&&!in[j]) m=dis[j],u=j;
		ans[i]=dis[u];
		in[u]=1;
//		cout<<u<<" "<<dis[u]<<" "<<ans[i]<<endl;
		for(int v=1;v<=n;v++){
			if(u!=v&&!in[v]){
				dis[v]=Min(dis[v],Dis(u,v));
			}	
		} 
	}
	sort(ans+1,ans+1+n,cmp);
	printf("%.2lf",ans[1+Q/2]);
	return 0;
}
每两个电话间可以删去这两个电话与树组成的回路上的一条边
只要把电话设置在最边上就可以删去树上任意一条边
100pts:
CPP
#include<bits/stdc++.h>
using namespace std;
const int N=505;
const int Max=20000;
struct Node{
	int x,y;
}node[N];
double dis[N],ans[N];
int in[N],n,Q;
double Dis(int a,int b){
	return sqrt((node[a].y-node[b].y)*(node[a].y-node[b].y)+
				(node[a].x-node[b].x)*(node[a].x-node[b].x));
}
double Min(double a,double b){return a<b?a:b;}
bool cmp(double a,double b){return a>b;}
int main(){
	cin>>Q>>n;
	for(int i=1;i<=n;i++){
		cin>>node[i].x>>node[i].y;
		dis[i]=Max;
	}
	int m=Max,u,v;
	dis[1]=0;
	for(int i=1;i<=n;i++){
		m=Max;
		for(int j=1;j<=n;j++)
			if(dis[j]<m&&!in[j]) m=dis[j],u=j;
		ans[i]=dis[u];
		in[u]=1;
//		cout<<u<<" "<<dis[u]<<" "<<ans[i]<<endl;
		for(int v=1;v<=n;v++){
			if(u!=v&&!in[v]){
				dis[v]=Min(dis[v],Dis(u,v));
			}	
		} 
	}
	sort(ans+1,ans+1+n,cmp);
	printf("%.2lf",ans[Q]);
	return 0;
}
可以用堆优化一下

评论

0 条评论,欢迎与作者交流。

正在加载评论...