堆优化的dijkstra板子

本文介绍了在LeetCode竞赛中如何使用Dijkstra算法解决3017题,涉及邻接表和链式前向星数据结构的实现,以及堆排序在寻找最短路径中的应用。
摘要由CSDN通过智能技术生成

第 377 场周赛 - 力扣(LeetCode)

之前力扣周赛有一次,都没想到用这个,,后来自己写了

然后这次周赛又考了,我没有板子QAQ,普通板子还超时了,所以补一篇

第 381 场周赛 - 力扣(LeetCode)3017. 按距离统计房屋对数目 II - 力扣(LeetCode)

————

1.第一个结构体dis_node把下标该下标距起点的当前最短路放入一个结构体了,这样做堆排的时候方便找下标。

2.cmp仿函数是用于堆排比较器的,(试过greater<自己的类型>()是不行的。。)

建的小根堆快速选择当前最短路(dijkstra的原理) 

3.

①tmpdis代表节点之间的距离,有的时候就是1,自己设置吧,dijkstr主函数中算距离用。

dij代表此点到所有点的最短路,所以我放参数列表当输出型参数了,许多题可能要用到。

③vector<set<int>>arr代表通路,用set可以去重(有的题可能是多重图,即含平行边)。

④加强:自己到自己不用,所以if一下。因为next = cur,会吧dij[cur]给覆盖掉造成错误

关于初始化,可以把dij都初始化为LLONG_MAX,然后给起始点赋值为0。

本板子也可以直接初始化为0。

邻接表版:

    int tmpdis = 1;
    struct dis_node//放堆里面比长度,但是想知道端点
    {
        int dis;
        int next;
        bool operator > (const dis_node& a)
        {
            return dis > a.dis;
        }
        dis_node(int d, int n)
        {
            dis = d; next = n;
        }
    };
    void dijkstr(vector<int>&dij,vector<set<int>>& arr, int ori, int n)
    {
        priority_queue<dis_node, vector<dis_node>, greater<>>heap;
        
        vector<int>barr(arr.size());
        int cur = ori;
        while (1)
        {
            //该次点所有可走的
            for (auto next : arr[cur])
            {
                if(next == cur)continue;//不走自己

                //next就是下一个点(邻接表
                if (dij[next] == 0)
                    dij[next] = dij[cur] + tmpdis;
                else
                    dij[next] = min(dij[next], dij[cur] + tmpdis);
                heap.push(dis_node(dij[next], next));
            }
            //该点已使用,已最短,无需再抵达
            barr[cur] = 1;
            //最短路中找最短,同时可抵达的
            while (heap.size())
            {
                if (barr[heap.top().next] == 0)
                    break;
                heap.pop();
            }
            if (heap.size() == 0)break;
            cur = heap.top().next;
            heap.pop();
        }
    }

 链式前向星版:

int tmpdis = 1;
struct dis_node//放堆里面比长度,但是想知道端点
{
    int dis;
    int next;
    bool operator < (const dis_node& a)
    {
        return dis < a.dis;
    }
    dis_node(int d, int n)
    {
        dis = d; next = n;
    }
};
class cmp
{
public:
    bool operator()(dis_node a, dis_node b)
    {
        return a.dis > b.dis;//
    }
};
void dijkstr(vector<int>& dij,  int ori, int n)
{
    priority_queue<dis_node, vector<dis_node>, cmp>heap;
 
    vector<int>barr(n+2);
    int cur = ori;
    while (1)
    {
		for (int i = head[cur]; i; i = nxt[i])
		{
			if (node[nxt[i]] == cur)continue;
 
			if(dij[node[i]] == 0)
				dij[node[i]] = dij[cur] + val[i];
			else
				dij[node[i]] = min(dij[node[i]], dij[cur] + val[i]);
 
			heap.push(dis_node( dij[node[i]], node[i] ));
		}
 
        //该点已使用,已最短,无需再抵达
        barr[cur] = 1;
        //最短路中找最短,同时可抵达的
        while (heap.size())
        {
            if (barr[heap.top().next] == 0)
                break;
            heap.pop();
        }
        if (heap.size() == 0)break;
        cur = heap.top().next;
        heap.pop();
    }
}

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值