HDU 1875 畅通工程再续 (最小生成树)

63 阅读1分钟

题意:

注意把距离小于10米和距离大于1000的两个岛的距离设置为无穷大,调用prim函数结束后检查一下图是否连通即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
using namespace std;
const int N=105;
#define inf 0x3f3f3f3f
int n,vis[N];
double dis[N],ma[N][N],cost;
struct {
	int x,y;
}is[N];
double qiu(int x1,int y1,int x2,int y2){
	double te=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
	return sqrt(te); 
}
void mem(){
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++){
			double te=qiu(is[j].x,is[j].y,is[i].x,is[i].y);	
			if(i==j) ma[i][j]=0;
			else if(te<10||te>1000) ma[i][j]=inf;
			else ma[i][j]=te;
		}
} 
void prim(){
	for(int i=1;i<=n;i++){
		dis[i]=ma[1][i];
		vis[i]=0;
	}
	dis[1]=0;
	vis[1]=1;
	for(int i=1;i<=n;i++){
		 double mi=inf;
		 int mb;
		for(int j=1;j<=n;j++){
			if(!vis[j]&&dis[j]<mi){
				mi=dis[j];
				mb=j;
			}
		}
		if(mi==inf) break;
		vis[mb]=1;
		cost+=dis[mb];
		for(int i=1;i<=n;i++){
			if(!vis[i]&&ma[mb][i]<dis[i]){
				dis[i]=ma[mb][i];
			}
		}
		
	}
	
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
			cost=0;
		scanf("%d",&n);
		int a,b;
		for(int i=1;i<=n;i++){
			scanf("%d%d",&a,&b);
			is[i].x=a;is[i].y=b;
		}
		mem();
		prim(); 
		int flag=1;
		for(int i=1;i<=n;i++){
			if(!vis[i]) {
				flag=0;
				break;
			}
		}
		if(flag)
		printf("%.1lf\n",cost*100);
		else puts("oh!");
	}
	
	return 0;
}


\