leetcode周赛284T4-得到要求路径的最小带权子图(如何利用STL来写堆优化版迪杰斯特拉算法)

该博客讨论了如何使用堆优化的迪杰斯特拉算法寻找三个节点dest, src1, src2到公共节点的最短路径。在C++STL不支持堆节点修改的情况下,通过比较堆中节点的路径长度来避免冗余操作。算法实现中包含了一个自定义比较函数cmp,用于调整优先级队列的顺序。最终,通过遍历所有可达节点并计算路径总和,找到最短路径的总权重。
摘要由CSDN通过智能技术生成

在这里插入图片描述
在这里插入图片描述

  • 考察最优解具有的性质:dest,src1,src2结点到某个公共结点的最短路
  • 堆优化版迪杰斯特拉算法涉及修改堆中结点的情况,但C++ STL本身并不支持堆结点修改。也无法找到那个堆结点,删除再插入新的。
  • 考虑迪杰斯特拉算法的执行过程。后面出队的结点的dist一定大于等于前面出队的结点。所以如果后面结点在前面的结点已经遇到过即这个后面遇到的结点在堆中存储的路径长度大于现有长度dist则直接将这个结点舍去。避免重复的松弛操作。
class Solution {
struct cmp{
    bool operator () (pair<int,long> a, pair<int,long> b){
        if(a.second < 0) return true;
        if(b.second < 0) return false;
        return a > b;
    }
};
public:
    long long minimumWeight(int n, vector<vector<int>>& edges, int src1, int src2, int dest) {
        
        long long dist1[n];
        long long dist2[n];
        long long dist3[n];
        memset(dist1,-1,n*sizeof(long long));
        memset(dist2,-1,n*sizeof(long long));
        memset(dist3,-1,n*sizeof(long long));
        vector<pair<int,int>> adjmap[n];
        vector<pair<int,int>> adjmap_fan[n];
        for(int i = 0;i<edges.size();i++)
        {
            adjmap[edges[i][0]].push_back(make_pair(edges[i][1],edges[i][2]));
            adjmap_fan[edges[i][1]].push_back(make_pair(edges[i][0],edges[i][2]));
        }
        dijktra(n,adjmap,src1,dist1);dijktra(n,adjmap,src2,dist2); dijktra(n,adjmap_fan,dest,dist3);
        long long ans  = -1;
        for(int i = 0;i<n;i++) 
        {
            if(dist1[i] >= 0 && dist2[i] >= 0 && dist3[i] >=0)  //均可以到达
            {
                if(ans < 0) ans = dist1[i] + dist2[i] + dist3[i];
                else ans = min(ans,dist1[i] + dist2[i] + dist3[i]);
            }
        }
        return ans;
    }

    void dijktra(int n,vector<pair<int,int>> adjmap[],int src,long long dist[])
    {
        dist[src] = 0;  //到源节点的距离为0
        priority_queue<pair<int,long long>,vector<pair<int,long long>>,cmp> q; q.push(make_pair(src,0));
        while(!q.empty())   
        {
                
                int u = q.top().first;
                if(q.top().second > dist[u] ) {q.pop();continue;}   //注意这里的舍弃操作
                q.pop();
                //relax
                for(pair<int,int> a:adjmap[u])
                {
                    int v = a.first; int w = a.second;
                    if(dist[v] == -1 || (dist[v] >= 0 && dist[v] > dist[u] +(long long) w ))
                    {    
                        dist[v]  = dist[u] +(long long) w ;
                        q.push(make_pair(v,dist[v]));
                    }
                }
        }        
    }

};
  • 同时,总结下cmp结构体里的operator:
struct cmp{
    bool operator () (pair<int,long> a, pair<int,long> b){
        if(a.second < 0) return true;
        if(b.second < 0) return false;
        return a > b;
    }
};
  • 如果返回真,则程序将a放在b后面,否则如果返回假,则程序将b放在a后面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值