2019 GDUT 新生专题Ⅲ K题

K - 畅通工程再续

题目链接
题目大意:计算连通的最短路线的花费,但是要满足两点之间距离不小于10和不大于1000,如果不能连通,就输出oh!,能就输出最少花费。
思路:最小生成树问题,不过不是直接套prim模板了,做些小修改,详情看代码。
代码

#include <cstdio>
#include <algorithm>
#include <math.h>
using namespace std;
const int MAX=105;
const int inf=999999999;
double cost[MAX][MAX],mincost[MAX];
int n;
bool used[MAX];
struct point{
	double x,y;
}e[MAX]; 
double prim(){
	double res=0;
	mincost[0]=0;
	int cnt=0;
	while(true){
		int v=-1;
		for(int i=0;i<n;i++){
			if(!used[i]&&(v==-1||mincost[i]<mincost[v])) v=i;
		}
		if(v==-1||(v!=0&&mincost[v]==inf)) break;//如果所有点都已经用过或者无法继续连通了,就退出。 
		cnt++;//计数器,cnt-1就是最小生成树的边数。 
		used[v]=true;
		res+=mincost[v];
		for(int i=0;i<n;i++)
		mincost[i]=min(mincost[i],cost[v][i]);
	}
	if(cnt==n) return res;//如果cnt-1==n,就说明可以连通。(最小生成树边数=顶点数-1) 
	else return -1; 
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		fill(mincost,mincost+MAX,inf);
		fill(used,used+MAX,false);
		for(int i=0;i<n;i++){
			scanf("%lf%lf",&e[i].x,&e[i].y);
		}
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				cost[i][j]=sqrt((e[i].x-e[j].x)*(e[i].x-e[j].x)+(e[i].y-e[j].y)*(e[i].y-e[j].y));
				if(cost[i][j]<10||cost[i][j]>1000) cost[i][j]=inf;//如果边权大于1000或小于10,则不存在该边,设为inf。 
			}
		}
		double res=prim();
		if(res==-1) puts("oh!");
		else{
			res=res*100;
			printf("%.1f\n",res);
		}
	}
	return 0;
}
2019 GDUT 新生专题Ⅲ K题2019 GDUT 新生专题Ⅲ K题 Jhaogee 发布了23 篇原创文章 · 获赞 0 · 访问量 378 私信 关注
上一篇:全面了解 Code Spliting 和 Lazy Loading,前端性能优化实用干货


下一篇:单例模式(饿汉模式、懒汉模式、静态内部类、枚举单例)反射破解