题目链接
模板题
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语言教材中,局部变量称为自动变量。