HDU 3405 poj 3771 最小生成树+删点

本文详细介绍了Prim算法的应用场景及实现过程,特别针对边数较多的情况,使用Prim算法来求解最小生成树问题。通过具体的C语言代码示例,帮助读者理解算法的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


边数较少可以用Kruskal,因为Kruskal算法每次查找最短的边。
边数较多可以用Prim,因为它是每次加一个顶点,对边数多的适用。
用Prim。

#include<stdio.h>
#include<string.h>
#include<math.h>
const double INF=99999;
struct z{
	int x,y;
	int cas;
}node[300];
double xxx(int a,int b,int x,int y){
	return sqrt((a-x)*(a-x)*1.0+(b-y)*(b-y)*1.0);
}
double small(double a,double b){
	return a>b?b:a;
}
double mat[2000][2000];
double map[2000][2000];
double prim(int n){
    int i,min_i,j;
	double Min,sum=0;
    double dis[3000];
    int flag[3000];
    for( i=1 ; i <=n ; i++ )
		dis[i] = mat[i][1];
    memset( flag, 0, sizeof(flag));
    flag[1] = 1;
	for( i=2 ; i <=n ; i++ ) {
		Min = INF;min_i=i;
		for( j=2 ; j <=n ; j++ ){
			if(flag[j]==0 && dis[j]<Min){
				Min=dis[j];
				min_i=j;
			}
		}
		if(Min==INF)
			break;
		sum += Min;
		flag[min_i] = 1;
		for( j=2 ; j <=n ; j++ ){
			if(flag[j]==0 && dis[j]>mat[min_i][j])
				dis[j] = mat[j][min_i];
		}
    }
	return sum;
}
int main(){
	int t,n,i,j,k;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(i=1;i<=n;i++){
			scanf("%d %d",&node[i].x,&node[i].y);
			node[i].cas=i;
		}
		int num=0;
		
		for(i=1;i<=n;i++){
			for(j=1;j<=n;j++){
				mat[i][j]=INF;
			}
		}
		for(i=1;i<=n;i++){
			for(j=1;j<=n;j++){
				if(i==j)
					continue;
				int x=node[i].cas;
				int y=node[j].cas;
				map[x][y]=xxx(node[i].x,node[i].y,node[j].x,node[j].y);
				map[y][x]=xxx(node[i].x,node[i].y,node[j].x,node[j].y);
				num++;
			}
		}
		double ans=INF*2;
		for(i=1;i<=n;i++){
			for(j=1;j<=n;j++){
				for(k=1;k<=n;k++){
					mat[j][k]=map[j][k];
				}
			}
			for(j=1;j<=n;j++){
				mat[j][i]=INF-1;
				mat[i][j]=INF-1;
			}
			ans=small(prim(n),ans);
			ans=ans;
		}
		printf("%.2lf\n",ans-INF+1);
	}
}


转载于:https://www.cnblogs.com/kewowlo/p/4002523.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值