📜  Prim的算法在STL中使用priority_queue(1)

📅  最后修改于: 2023-12-03 15:03:52.079000             🧑  作者: Mango

Prim's算法在STL中使用priority_queue

简介

Prim's算法是一种用于解决最小生成树问题的贪心算法,它通过选择当前集合到未访问节点的最小边来构建最小生成树。在STL中,我们可以使用priority_queue数据结构来辅助实现Prim's算法。

Prim's算法流程
  1. 初始化一个空的最小生成树MST和一个空的顶点集合visited。
  2. 选择一个起始节点并将其标记为visited。
  3. 将起始节点所有的邻居顶点及对应的边加入到一个最小堆中(使用优先队列priority_queue实现),其中边的权重作为优先级。
  4. 从最小堆中取出权重最小的边及其相邻顶点。
  5. 如果相邻顶点未被访问过,则将该顶点及相应边加入到MST中,并将该顶点标记为visited。
  6. 重复步骤4和步骤5,直到所有的顶点被访问。
  7. 最小生成树MST即为Prim's算法的结果。
实现Prim's算法的代码片段
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

// 定义边的结构
struct Edge {
    int src, dest, weight;
};

// 定义比较函数用于优先队列的排序
struct Compare {
    bool operator()(Edge const& e1, Edge const& e2) {
        // 边的权重越小,优先级越高
        return e1.weight > e2.weight;
    }
};

void prim(vector<vector<pair<int, int>>>& graph, int start) {
    int vertices = graph.size();

    // 存储最小生成树的边
    vector<Edge> mst;

    // 标记顶点是否被访问
    vector<bool> visited(vertices, false);

    // 定义优先队列(最小堆)
    priority_queue<Edge, vector<Edge>, Compare> pq;

    // 将起始节点及其邻居边加入优先队列
    for (auto neighbor : graph[start]) {
        int dest = neighbor.first;
        int weight = neighbor.second;
        pq.push({start, dest, weight});
    }

    visited[start] = true;

    while (!pq.empty()) {
        Edge e = pq.top();
        pq.pop();

        int dest = e.dest;

        // 如果相邻顶点已经被访问,跳过当前边
        if (visited[dest])
            continue;

        // 将边加入最小生成树
        mst.push_back(e);
        visited[dest] = true;

        // 将相邻顶点及边加入优先队列
        for (auto neighbor : graph[dest]) {
            int nextDest = neighbor.first;
            int weight = neighbor.second;
            pq.push({dest, nextDest, weight});
        }
    }

    // 打印最小生成树
    cout << "Minimum Spanning Tree:" << endl;
    for (auto edge : mst) {
        cout << edge.src << " -> " << edge.dest << " : " << edge.weight << endl;
    }
}

int main() {
    int vertices, edges;
    cout << "Enter the number of vertices: ";
    cin >> vertices;
    cout << "Enter the number of edges: ";
    cin >> edges;

    vector<vector<pair<int, int>>> graph(vertices);

    cout << "Enter the edges (src, dest, weight):" << endl;
    for (int i = 0; i < edges; i++) {
        int src, dest, weight;
        cin >> src >> dest >> weight;
        graph[src].push_back({dest, weight});
        graph[dest].push_back({src, weight});
    }

    int start;
    cout << "Enter the start vertex: ";
    cin >> start;

    prim(graph, start);

    return 0;
}

以上代码是一个使用Prim's算法和STL中的priority_queue实现的最小生成树的例子。输入顶点、边以及边的权重,然后输入开始的顶点,并输出最小生成树的结果。

总结

总之,Prim's算法是解决最小生成树问题的常用贪心算法,而STL中的优先队列(priority_queue)是实现Prim's算法的有效工具。优先队列通过调整边的优先级来确保选择权重最小的边,从而构建一个最小生成树。