//Dijkstra
#include <iostream>
#include <queue>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 50050;
struct edge {
int v;
};//边的另一个顶点(此题没有权重)
struct node {
int dis;//每个顶点到源点(1号点)的距离
int u;//顶点编号
bool operator>(const node& a) const {
return dis > a.dis;
}//重载大于号,用于升序排列
};
vector<edge> e[maxn];//邻接表,边的位置代表其中一个顶点
int dis[maxn];//每个顶点到源点(1号点)的距离
int vis[maxn];//是否已确定最短距离,初值为0
priority_queue<node, vector<node>, greater<node> > q;
//按dis升序排列顶点的优先队列,存储未确定最短距离的顶点
int dijkstra(int n, int s) { //s:source源点
memset(dis, 63, sizeof(dis));//63=0x3f 表示无穷大
dis[s] = 0;
q.push({dis[s], s});
while (!q.empty()) {
int u = q.top().u;//取出距离最小的顶点
q.pop();
if (vis[u]) continue;
for (auto ed : e[u]) {//ed:edge,e[u]:与第u个顶点相连的顶点
int v = ed.v;
if (dis[v] > dis[u] + 1) {
dis[v] = dis[u] + 1;
q.push({dis[v], v});
}
}
vis[u] = 1;
}
return dis[n];
}
int main() {
int n, m;
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
e[u].push_back({v});
e[v].push_back({u});
}
if (dijkstra(n, 1)<0x3f3f3f3f)cout<<dis[n];
else cout<<-1;
return 0;
}
审题发现是求解非负权无向稀疏图上单源最短路径,使用优先队列实现的Dijkstra如果同一个点的最短路被更新多次,因为先前更新时插入的元素不能被删除,也不能被修改,只能留在优先队列中,故优先队列内的元素个数是O(m)的,时间复杂度O(mlogm)。在OI Wiki提供的模板的基础上实现,感觉足够简洁优美。

京公网安备 11010502036488号