最小生成树[Prim]

问题:参照[Kruskal]
原理:
Prim算法使用的是一种贪心的思想,通过从一个点出发,选择所有链接这一个点的边中,选择权值最小的边。
在选择了这一条边之后,优化之前的边的选择方案。在最后,把所有的最小边之和加起来就得到了最小的方案
来看一个例子
最小生成树[Prim] - 赵子睿 - 赵子睿的博客

 首先,在第一个点的所有链接的边中,选择链接到5的边,设置到达2的最小边为7。
从5出发,发现到4的边最短,选择这一条边。将到达3的最小边设置为2
查询4号点,发现边的长度为6,比到达3的最小边2要长,返回到出发点为5,链接到3
查询3,发现到达2号店的5要比之前记录的长度要短,选择这一条边。发现全部点都被访问了一次,结束循环。

最后得到这样的一幅图,组成了最小生成树
最小生成树[Prim] - 赵子睿 - 赵子睿的博客
 计算到这一个图的最小生成树的长度为12
考程序:

#include<stdio.h>
#include<stdlib.h>

const int MAXN = 1010,
INF = 0x7ffffff;

int n,m;
int min_cost;
int adj[MAXN][MAXN];
bool f[MAXN];
int len_min[MAXN];
int from_num[MAXN];

void _Prim()
{
for(int i=1;i<n;i++)
{
int _min=INF,from;
for(int j=1;j<=n;j++)
if(!f[j] && len_min[j] < _min)//寻找最小边
{
_min=len_min[j];
from=j;
}

min_cost+=adj[ from_num[from] ][from];
f[ from ]=true;//记录为访问过

for(int j=1;j<=n;j++)//优化最小边
if(!f[j] && adj[from][j] < len_min[j])
{
len_min[j]=adj[from][j];
from_num[j]=from;
}
}
}

int main()
{
scanf("%d%d",&n,&m);

for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) 

if(i==j) adj[i][j]=0;

else adj[i][j]=INF;


for(int i=0;i<m;i++)
{
int u,v,len;
scanf("%d%d%d",&u,&v,&len);

adj[u][v]=adj[v][u]=len;//创造邻接矩阵
}

for(int i=1;i<=n;i++)
{
len_min[i]=adj[1][i];//初始化到达1号节点
from_num[i]=1;
}

min_cost=0;
f[1]=true;//一号节点设置为访问过

_Prim();

printf("%d\n",min_cost);
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值