AcWing(850)-----Dijkstra求最短路 II

题目链接

模板题

1. 题中m,n的数据范围都为100000,所以用朴素dijkstra行不通,需要用优先队列优化

———————————————————————————————————————————————————————————————

邻接矩阵实现的dijkstra算法的复杂度是O(V²)。使用邻接表的话,更新最短距离只需要访问每条边一次即可,因此这部分的复杂度是O(E).但是每次要枚举所有的顶点来查找下一个使用的顶点,因此最终复杂度还是O(V²)。在|E|比较小时,大部分的时间都花在了查找下一个使用的顶点上,因此需要使用合适的数据结构进行优化。

需要优化的是数值的插入(更新)和取出最小值两个操作,因此使用最小堆就可以了。把每个顶点当前的最短距离用堆来维护,在更新最短距离时,把对应的元素往根的方向移动以满足堆的性质。而每次从堆中取出的最小值就是下一次要用的顶点。这样堆中的元素共有O(V)个,更新和取出的操作有O(E)次,因此整个算法的复杂度是O(ElogV)。
下面是使用STL的priority_queue实现。在每次更新时往堆里插入当前最短距离和顶点的值对。插入的次数是O(E)次,当取出的最小值不是最短距离的话,就丢弃这个值。这样整个算法也可以在同样的时间内完成。
———————————————————————————————————————————————————————————————

2.不能使用邻接矩阵存储图,需要使用邻接表

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <vector>
#include <map>
#include <algorithm>
#include <string.h>
#include <cstring>
using namespace std;
const int  MAX=100010;
const int  INF=100000000;
int n,m;
int i,j;
int x,y,z;
struct node 
{
    int v;
	int w;
};
int dis[MAX];
int book[MAX];
typedef pair<int,int> P;//边权,终点
vector <node> adj[MAX];
void dijkstra()
{
	memset(book,0,sizeof(book));
    for(int i=1;i<=n;i++)
    {
    dis[i]=INF;
    }
	dis[1]=0;
	priority_queue<P,vector<P>,greater<P> > heap;//最小堆
	heap.push({0,1});
	while(heap.size())
	{
		auto t=heap.top();  
		heap.pop();
		int ver=t.second;
		int distance=t.first;
		if(book[ver])
			continue;
		book[ver]=1;
		for(i=0;i<adj[ver].size();i++)
		{
			int num=adj[ver][i].v;
			if(book[num]==0&&dis[ver]+adj[ver][i].w<dis[num])
			{
              dis[num]=dis[ver]+adj[ver][i].w;
			  heap.push({dis[num],num});
			}
		}
	}

}
int main()
{
    scanf("%d%d",&n,&m);
	for(i=0;i<m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		node temp;
		temp.v=y;
		temp.w=z;
		adj[x].push_back(temp);
	}
	dijkstra();
	if(dis[n]!=INF)
	printf("%d\n",dis[n]);
	else
	printf("-1\n");
	return 0;
}

3. 小结:auto的用法

仅在语句块内部使用,初始化可为任何表达式,其特点是当执行流程进入该语句块的时候初始化可为任何表达式,autor对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销。在函数内部定义的变量成为局部变量。在某些C语言教材中,局部变量称为自动变量。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值