poj 1258 数据结构 求最小生成树

poj1258分析由题意分析得该题目为最小生成树的裸题
首先介绍下最小生成树的相关概念:
带权图:边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权。
最小生成树(MST):权值最小的生成树。
生成树和最小生成树的应用:要连通n个城市需要n-1条边线路。可以把边上的权值解释为线路的造价。则最小生成树表示使其造价最小的生成树。
所以,接下来介绍下求最小生成树的Prim算法如下:
(1)普利姆算法(prim)求最小生成树(MST)
下图是一个简单的带权图:
在这里插入图片描述

首先任意选择一个结点:
在这选择v4为第一个结点,v4相邻的路径有两个,选择最小的一个v3构成最小生成树的第一个路径,如下:
在这里插入图片描述
接下来,从v3结点选择相邻的最短路径,一次,进行,v4->v3->v1->v2->v6->v5,结果如下:最小生成树

所以该题如下:`#include
#include <string.h>
#include <stdio.h>
/infinity
//表示总路长最大值
//INF ≥ 单条路径最大值(100,000) × (MAXTOWNN(100)- 1)
#define INF 10000000
#define TRUE 1
#define FALSE 0

//maximum number of towns
//城镇数量的最大值
#define maxtownn 101

typedef char BOOL;

int d[maxtownn][maxtownn]; //i到j的距离
BOOL v[maxtownn]; /[i]表示i号镇是否被纳入集合中,即have been visited
int dp[maxtownn]; //dp[j]表示动态规划记录当前集合外的点j到集合内点的最小距离

int prim(int n) //prim求最小生成树
{
int i, j;
int min, minj;
int ans;
//初始化
dp[1] = 0;
for ( i = 2; i <= n; i++ )
dp[i] = d[1][i];
memset( v+1, FALSE, n * sizeof(BOOL));
v[1] = TRUE;
//将n个点全部纳入集合后就代表算法成功结束
for ( ans = 0, i = 2; i <= n; i++ )
{
//找出当前集合外到集合内点最短距离以及该集合外的点
for ( min = INF, minj = 0, j = 2; j <= n; j++ )
if ( !v[j] && dp[j] < min )
{
min = dp[j];
minj = j;
}
if (!minj) //集合外的点到集合内的点都不可达,表示无最小生成树
return INF; //那么答案自然就是无穷大了
v[minj]= TRUE;
ans+= min;
for ( j = 2; j <= n; j++ )
if ( !v[j] && d[minj][j] < dp[j] )
dp[j] = d[minj][j];
}
return ans;
}

int main()
{
int n;
int i, j;

while ( ~scanf("%d", &n) )
{	
	for ( i = 1; i <= n; i++ )
		for ( j = 1; j <= n; j++ )
			scanf("%d", &d[i][j]);		
		printf("%d\n", prim(n));
}	
return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值