最小生成树——Prim算法

最小生成树

如有不足,欢迎指正。

 

先来看一张图。


我们要给1-77个城市修路,使得任意两个城市之间都可达,并且要使总花费最小,现在告诉你从a城市到b城市修一条路花费为c

那么问题来了,你要如何使得城市既能两两连通又花费最小呢?

要暴力列举吗?写下任何一种可行的情况去汇总比较?

NoNoNo,早已在1957年普里姆同学就已经解决了这个问题,为了纪念小普同学,后来人们就把这种算法叫做普里姆算法,为小普同学鼓掌。

ok,我们就来看看小普同学是如何解决这个问题的。

首先,我们需要一个节点,假设从节点1开始。找出代价最小的一条。10,很明显12之间修路代价最小。此时,花费为1.

注:dis[]数组存放的是所有已遍历节点与节点1-7可达的最小值。

现在修建到节点3的最小代价为2,节点4的最小代价为8,节点5的最小代价为10,节点6无路可走,节点7最小代价为8修建13之间的公路。此时,花费为3.

注:已遍历节点dis[]值不再改变。

此时,对于节点4我们既可以修建1->4,也可以修建3->4,但3->4代价最小因此dis[4]=2;同理dis[5]=1;此时,花费为4.


花费为5;      sum=1+2+1+1


花费为9


花费为14

 

OK,到现在修路结束,我们的总花费为14.怎么样?看懂了吗?

算法代码部分

#define INF 0x3f3f3f3f
int Map[110][110];//记录节点间关系,可达记为1,否则记为0;
bool vis[110];//记录节点是否被遍历;
int dis[110];
void Prim()
{
    memset(vis,false,sizeof(vis));
    int i,j;
    int sum=0;//记录最小花费
    //将1节点与其余节点的可达关系存入到dis数组;
    for(i=1; i<=n; i++)
        dis[i]=Map[1][i];
    vis[1]=true;
    for(i=1; i<n; i++)
    {
        int m=INF;//记录i节点与其余节点的最短可达代价        
        int pos;        
        //寻求与i节点有关的代价最小的节点        
        //若节点存在,pos记录该节点的位置,m记录可达代价        
        for(j=1;j<=n;j++)        
        {           
            if(!vis[j]&&dis[j]<m)                
            pos=j,m=dis[j];        
        }        
        if(m==INF) break;//查找结束        
        vis[pos]=true;        
        sum+=m;//计算到当前为止所花费的代价        
              
        for(j=1;j<=n;j++)//更新dis;              
            if(!vis[j]&&dis[j]>Map[pos][j])                
                dis[j]=Map[pos][j];    
    }
        printf("%d\n",sum);
}


 

SDUT上一道最小生成树的题,有空可以做一做。

图结构练习——最小生成树

 

 

 


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值