博客
关于我
Prim求MST最小生成树
阅读量:795 次
发布时间:2023-03-04

本文共 2745 字,大约阅读时间需要 9 分钟。

Prim算法是一种求最小生成树(MST)的高效方法,其核心思想与Dijkstra算法中的松弛操作相似。Prim算法通过逐步松弛边权,最终构建连接所有节点的最小权重树。

Prim算法的核心思想

Prim算法选择一个起始点(通常随机选取或固定为节点1),然后依次松弛与该松弛点相连的节点。具体步骤如下:

  • 初始化所有节点的距离(dis)为无穷大,起始点的距离设为0。
  • 将起始点标记为已访问(vis),并将其加入优先队列。
  • 每次从优先队列中取出距离最小的节点u,松弛u与其未访问邻接节点v的边。如果u-v边的权重小于当前v的距离,则更新v的距离,并将v加入优先队列。
  • Prim算法的贪心机制

    Prim算法的贪心机制在于每次选择距离当前松弛点最近的节点,更新其最短边。这种机制确保了每次松弛操作都选择了当前可用最短边,从而逐步构建MST。

    Prim算法的代码实现

    以下是Prim算法在邻接矩阵和邻接表两种数据结构下的实现示例。

    邻接矩阵实现

    #include 
    #include
    #include
    #include
    using namespace std;typedef int insert;const int INF = 0x3f3f3f3f;const int N = 5000 + 100;insert edges[N][N], dis[N], vis[N];insert n, m, x, y, z;long long sum;void value() { memset(edges, INF, sizeof(edges)); memset(dis, INF, sizeof(dis)); for (int i = 1; i <= m; ++i) { cin >> x >> y >> z; if (edges[x][y] > z || edges[y][x] > z) { edges[x][y] = z; edges[y][x] = z; } } dis[1] = 0;}void prim() { for (int k = 1; k <= n; ++k) { insert minn = INF, pos; for (int i = 1; i <= n; ++i) { if (!vis[i] && dis[i] < minn) { minn = dis[i]; pos = i; } } vis[pos] = true; for (int i = 0; i < n; ++i) { if (!vis[i] && dis[i] > edges[pos][i]) { dis[i] = edges[pos][i]; } } }}int main() { cin >> n >> m; value(); prim(); for (int i = 1; i <= n; ++i) { sum += dis[i]; } cout << "最小生成树的总权值"; for (int i = 1; i <= n; ++i) { cout << " " << dis[i]; } cout << endl;}

    邻接表实现

    #include 
    #include
    #include
    #include
    #include
    using namespace std;typedef int insert;const int INF = 0x3f3f3f3f;const int N = 2e5 + 200;insert n, m, x, y, z, dis[N], sum, startpoint;bool vis[N];vector
    vt[N];struct Node { int to, w;};void initial_value() { memset(dis, INF, sizeof(dis)); for (int i = 1; i <= m; ++i) { cin >> x >> y >> z; Node node; node.to = y; node.w = z; vt[x].push_back(node); node.to = x; vt[y].push_back(node); } dis[startpoint] = 0;}void prim() { for (int k = 1; k <= n; ++k) { insert minn = INF, pos; for (int i = 1; i <= n; ++i) { if (!vis[i] && dis[i] < minn) { minn = dis[i]; pos = i; } } vis[pos] = true; for (auto& neighbor : vt[pos]) { if (!vis[neighbor.to] && dis[neighbor.to] > neighbor.w) { dis[neighbor.to] = neighbor.w; } } }}int main() { cin >> n >> m >> startpoint; initial_value(); prim(); sum = 0; for (int i = 1; i <= n; ++i) { sum += dis[i]; } for (int i = 1; i <= n; ++i) { cout << "--" << dis[i] << " "; } cout << endl;}

    总结

    Prim算法通过松弛操作和贪心机制高效求解MST,适用于稀疏图。其核心在于每次选择当前最近的未访问节点,逐步扩展MST。代码实现采用邻接矩阵或邻接表,根据实际需求选择合适的数据结构。

    转载地址:http://gmxfk.baihongyu.com/

    你可能感兴趣的文章
    POJ1182(带权并查集)
    查看>>
    Qt笔记——Qt初探、PyQt5和Qt5
    查看>>
    poj1190生日蛋糕
    查看>>
    POJ1218 HDU1337 ZOJ1350 UVALive2557 THE DRUNK JAILER
    查看>>
    poj1222 EXTENDED LIGHTS OUT(gauss)
    查看>>
    POJ1240 m叉树
    查看>>
    Poj1328--Radar Installation(区间选点)
    查看>>
    POJ1384Piggy-Bank(DP)
    查看>>
    POJ1417 True Liars —— 并查集 + DP
    查看>>
    Poj1459 Power Network 预流推进
    查看>>
    POJ1502(MPI Maelstrom)
    查看>>
    poj1568 Find the Winning Move[极大极小搜索+alpha-beta剪枝]
    查看>>
    poj1730 - Perfect Pth Powers(完全平方数)(水题)
    查看>>
    poj1753——Flip Game
    查看>>
    poj1936 假期计划第一水
    查看>>
    poj1958-汉诺四塔问题(三种方法)
    查看>>
    poj1988(并查集)
    查看>>
    POJ2007+几何+极角排序
    查看>>
    poj2039
    查看>>
    poj2135(简单的最小费用流问题)
    查看>>