求最小生成树两种算法

本文深入探讨了最小生成树的概念,介绍了Prim算法的实现过程,包括如何构建无向图,如何选择最小权重边来逐步构建最小生成树,以及如何通过算法求得最小生成树的总权重。文章提供了详细的代码示例,帮助读者理解算法的具体应用。

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

求最小生成树,两种算法,求输出权值的和。第一行n,m,n为顶点数,小于等于20,m边数,后面m行,每行一个边的信息,每行三个数,i j c,起点i,终点j,权值c,i,j大于等于1,无向图。

/*求最小生成树,,求输出权值的和。
 第一行n,m,n为顶点数,小于等于20,m边数,后面m行,每行一个边的信息,每行三个数
i j c,起点i,终点j,权值c,i,j大于等于1,无向图。*/

#include <iostream>
#include <cstring>
using namespace std;
#define mai 1001
int i,j,k;
int arr[mai][mai];
int prim(int arr[][mai],int n)//加点法
{
    //vis数组用来记录这个点是否已经加入最小生成树
    int vis[mai] = {0};
    
    //dis数组表示当前最小生成树(集体)的可以到达的非最小生成树的点的最小距离
    int dis[mai] = {0};
    
    memset(vis,0,sizeof(vis));
    int sum = 0,min = mai,number;
 
    for(i = 2;i <= n;i++)
        dis[i] = arr[1][i];//从1开始,dis数组初始化
        vis[1] = 1;
    
   //从第二次访问开始(并不是第二个点),控制一共访问n次,所有的点已访问
    for(i = 2;i <= n;i++)

    {
        min = mai;number = -1;//每次访问新点时重新赋值min
        for(j = 1;j <= n;j++)
        {
            if(vis[j] == 0 && dis[j] < min)
            {
                min = dis[j];
                number = j;//number记录当前最小权值的下标,方便vis标记
            }
        }
            //这个for执行完之后就可以找到dis数组里面的最小权值是min,对应的点是j
        sum += min;
      
        vis[number]=1;//将j点标记为已加入
        for(j = 1;j <= n;j++)
            if(vis[j] == 0 && arr[number][j] < dis[j])
                dis[j] = arr[number][j];
        
        
    }
    return sum;
    
    
}
int main()
{
    int n,m,i,j,c;
    cin >> n >> m;
    for(i = 0;i <= n;i++)
        for(j = 0;j <= n;j++)
            arr[i][j] = mai;
    for(i = 0;i < m;i++)
    {
        cin >> i >> j >> c;
        arr[i][j] = c;
        arr[j][i] = c;
    }
    int small = prim(arr,n);
    cout << small << endl;
    return 0;
}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int cost[1020][1020];//cost[u][v]表示边e=(u,v)的权值(不存在的情况下设为INF)
int mincost[1020];//从集合X出发的边到每个顶点的最小权值
bool used[1020];//顶点i是否包含在集合X中
int prime();
int n,m,i,j,c;
int main()
{
    cin >> n >> m;
    memset(cost,INF,sizeof(cost));
    for(int i = 0;i < m;i++)
    {
        cin >> i >> j >> c;
        cost[i][j] = min(c,cost[i][j]);
        cost[j][i] = min(c,cost[j][i]);
    }
    cout<<prime()<<endl;
    return 0;
    
}

int prime()
{
    for(int i = 1;i <= n;i++)
    {
        mincost[i] = INF;
        used[i] = false;
    }
    mincost[1] = 0;
    int res = 0;
    while(true)
    {
        int v = -1;//从不属于X的顶点中选取从X到其权值最小的顶点
        for(int u=1;u <= n;u++)
        {
            if(!used[u] && (v == -1 || mincost[u] < mincost[v]))
                v = u;
        }
        if(v == -1)break;
        used[v] = true;//把顶点v加入X
        res += mincost[v];//把边的长度加到结果里
        for(int u = 1;u <= n;u++)
            mincost[u] = min(mincost[u],cost[v][u]);
    }
    return res;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Αиcíеиτеǎг

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值