【Algorithm】Prim

 朴素版prim算法

时间复杂度是 O(n^2+m), n 表示点数,m 表示边数

int n;      // n表示点数
int g[N][N];        // 邻接矩阵,存储所有边
int dist[N];        // 存储其他点到当前最小生成树的距离
bool st[N];     // 存储每个点是否已经在生成树中


// 如果图不连通,则返回INF(值是0x3f3f3f3f), 否则返回最小生成树的树边权重之和
int prim()
{
    memset(dist, 0x3f, sizeof dist);

    int res = 0;
    for (int i = 0; i < n; i ++ )
    {
        int t = -1;
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;

        if (i && dist[t] == INF) return INF;

        if (i) res += dist[t];
        st[t] = true;

        for (int j = 1; j <= n; j ++ ) dist[j] = min(dist[j], g[t][j]);
    }

    return res;
}

 Prim算法求最小生成树

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 510, INF = 0x3f3f3f3f;

int n, m;
int g[N][N], dist[N];
bool st[N]; // 记录当前点在集合内还是集合外

int prim()
{
    memset(dist, 0x3f, sizeof dist);
    
    int res = 0;
    for (int i = 0; i < n; i++) {
        // 找一个最短边权的点
        int t = -1;
        for (int j = 1; j <= n; j++)
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        
        // 不是第一个取出的节点, 并且当前节点的距离为INF, 则表示没有和集合中点相连的边。  
        if (i && dist[t] == INF) return INF;
        
        // 写在前面,如果一个节点本身出现负环
        // 下面这句更新后, 会影响结果, 比如g[t][j], 当t = j,更新了g[t][t], 影响res结果
        // 比如4->4 -10, 更新后dist[4] = min(dist[4], g[4][4])
        if (i) res += dist[t];
        
        for (int j = 1; j <= n; j++) dist[j] = min(dist[j], g[t][j]);
        
        st[t] = true;
    }
    
    return res;
}

int main()
{
    scanf("%d%d", &n, &m);
    
    memset(g, 0x3f, sizeof g);
    
    while (m--) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        
        g[u][v] = g[v][u] = min(g[v][u], w);
    }
    
    int t = prim();
    
    if (t == INF) puts("impossible");
    else printf("%d\n", t);
    
    return 0;
}

### Prim算法的介绍 Prim算法是一种用于寻找加权无向图最小生成树(MST)的经典贪心算法。该算法通过逐步扩展一棵初始为空的树来构建MST,每次迭代都会选择连接当前树与剩余顶点间权重最小的一条边加入到正在生长中的树中直到所有节点都被覆盖为止[^1]。 ### Prim算法的具体实现方式 一种常见的Python实现如下所示: ```python import sys from collections import defaultdict class Graph: def __init__(self, vertices): self.V = vertices self.graph = [[0 for column in range(vertices)] for row in range(vertices)] def print_mst(self, parent): print("Edge \tWeight") for i in range(1, self.V): print(parent[i], "-", i, "\t", self.graph[i][parent[i]]) def min_key(self, key, mst_set): min_value = sys.maxsize for v in range(self.V): if key[v] < min_value and mst_set[v] is False: min_value = key[v] min_index = v return min_index def prim_mst(self): key = [sys.maxsize] * self.V parent = [None] * self.V key[0] = 0 mst_set = [False] * self.V parent[0] = -1 for cout in range(self.V): u = self.min_key(key, mst_set) mst_set[u] = True for v in range(self.V): if (self.graph[u][v] > 0 and not mst_set[v] and key[v] > self.graph[u][v]): key[v] = self.graph[u][v] parent[v] = u self.print_mst(parent) ``` 这段代码定义了一个`Graph`类,其中包含了执行普里姆算法所需的方法。此版本适用于稠密图表示法(邻接矩阵)。对于稀疏图,则可以考虑采用更高效的优先队列优化版以减少时间复杂度至O(E log V),这里E代表边的数量而V则是顶点数。 ### 应用场景实例分析 在网络设计领域内,比如计算机网络拓扑结构规划或是城市交通路网建设等方面,经常会遇到需要找到成本最低路径的问题。此时就可以利用Prim算法求解最优方案从而节省资源开销并提高效率。另外,在图像分割技术当中也能够见到它的身影——通过对像素间的相似程度建模成带权值的关系进而形成一张完整的连通图之后再应用上述提到的技术手段来进行处理得到理想的划分效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值