生成最小树prim

生成最小树之prim算法

在讲生成最小树时,我们先了解一下邻接矩阵

什么是邻接矩阵?

定义

       邻接矩阵是表示顶点之间相邻关系的矩阵。设G=(v,E)是一个图,其中V={v1,v2,....,vn}。G的邻接矩阵是一个具有下列性质的n阶方阵:

(1)对无向图而言,邻接矩阵一定是对称的,而且主对角线一定为零(在此仅讨论无向简单图),副对角线不一定为零,有向图则不一定如此。

(2)在无向图中,任一顶点的度为第i列(或第i行)所有非零元素的个数,在有向图中顶点i的出度为第i行所有非零元素的个数,而入度为第i列所有非零元素的个数。

(3)用邻接矩阵法表示图共需要n^2个空间,由于无向图的邻接矩阵一定具有对称关系,所以扣除对角线为零外,仅需要存储上三角形或下三角形的数据即可,因此仅需要n(n-1)/2个空间。

我们来看一个图

 

画的有点抽象但不影响我们进行学习,我们来看看,这个表其实这个表代表着每个节点和某些节点先连的情况,这样我们循环到某一个节点的时候就知道了这个点还可以到哪些点,然后我们在看看有权图矩阵,把里面的0变成一个大数就行了,这是避免权值相等。

我个人认为,生成最小树是一个带有权无向图。

 

废话不多说了很多废话,上 代码。


#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int a[5010][5010];
int book[5010];
int dis[5010];
int n,m;
long long coun=0;
int get_sum(int sum)
{
    dis[sum]=0;
    int cur;
    for(int i=1;i<=n;i++)//有m个节点 遍历n遍
    {
        cur=-1;
        for(int j=1;j<=n;j++)//从当前节点与其他节点联通的权值找最小值
        {
            if(book[j]==0&&(cur==-1||dis[j]<dis[cur]))
                cur=j;
        }
         //cout<<dis[cur]<<endl;
      if(dis[cur]>=INF)//提前结束,这里就不构成了图
        return INF;
      coun+=dis[cur];
      book[cur]=1;//表示这个点走过了,不用走了
      for(int k=1;k<=n;k++)
      {
          if(book[k]==0)//更新当前的最小值
            dis[k]=min(dis[k],a[cur][k]);
      }
    }
    return 0;
}
int main()
{scanf("%d%d",&n,&m);
    memset(a,0x3f,sizeof(a));//设置成一个很大的数
    memset(dis,0x3f,sizeof(dis));

    for(int i=1;i<=m;i++)//输入
    {
        int x,y,len;
        scanf("%d%d%d",&x,&y,&len);
        a[x][y]=min(len,a[x][y]);//因为是无向图,所以 1,2 2,1都是联通的都需要赋值
        a[y][x]=min(len,a[y][x]);
    }

     long long mm=get_sum(1);
      if(mm>=INF)
        printf("orz");
        else
            printf("%lld",coun);
    return 0;
}

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值