c++ 实现prim树的详细代码+注释

结合labuladong大佬的java代码写出来的,一开始找到几个感觉实现的有点复杂,自己写了个新手向的,希望对点进来的同学有所帮助!

我们以力扣1135题:最低成本联通所有城市 为例(其实只是minimumcost()这个函数)主要还是看Prim这个类的设计。

 

接下来就是代码实现:

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

template <typename T>
class cmp {
public:
    bool operator()(T a, T b)
    { return a[2] > b[2];}
};
class Prim
{
private:
    priority_queue<vector<int>, vector<vector<int>>, cmp<vector<int>>> pq; //优先级队列,小顶堆
    vector<bool> inMST; //记录哪些节点已经成为最小生成树的一部分
    int weightsum = 0; //记录已经连接的节点之间的权重
    vector<vector<vector<int>>> graph;//用邻接表表示的一幅图,这里的邻接表应该对应的两个节点都要记录,因为是个无向图
    //vector<int>表示三元组{from,to,weight}也就是一条边
public:
    Prim(vector<vector<vector<int>>> graph) :graph(graph) {
        //初始化,先往树里加一个点。
        int n = this->graph.size(); //图中有n个节点
        this->graph.resize(n);
        inMST.resize(n, false);
        inMST[0] = true;

        cut(0);//不断进行切分,像最小生成树中添加边
        while (!pq.empty())
        {
            vector<int> curedge = pq.top();
            pq.pop();
            if (inMST[curedge[1]]) continue;  //已经连接过的两个点就跳过,避免成环
            weightsum += curedge[2];
            inMST[curedge[1]] = true;
            cut(curedge[1]);
        }
    }

    //将点s的横切边加入优先级队列
    void cut(int s) {
        for (auto& it : graph[s])
        {
            if (inMST[it[1]]) continue;
            pq.push(it);
        }
    }

    //用于返回权重和
    int weightSum() {
        return this->weightsum;
    }

    // 判断最⼩⽣成树是否包含图中的所有节点 
    bool allConnected() {
        for (int i = 0; i < inMST.size(); i++) {
            if (!inMST[i]) return false;
            return true;
        }
    }
};
    //这里的测试函数minimumCost()是力扣的1135题给的用例,题目给出的邻接表需要进行一个重新建图
    int minimumCost(int n, vector<vector<int>>& conections)
    {
        vector<vector<vector<int>>> graph(n);
        for (auto& it : conections)
        {
            int u = it[0] - 1;
            int v = it[1] - 1;
            int weight = it[2];
            // 「⽆向图」其实就是「双向图」 
            // ⼀条边表示为{from, to, weight} 
            vector<int> vwc1 = { u, v, weight };
            vector<int> vwc2 = { v, u, weight };
            graph[u].push_back(vwc1);
            graph[v].push_back(vwc2);
        }
        
        Prim* prim = new Prim(graph);
        if (!prim->allConnected()) {
            // 最⼩⽣成树⽆法覆盖所有节点 
            return -1;
        }
        return prim->weightSum();
    }

如有问题,欢迎评论指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值