最短路之保存最短路径
思路:设置一个pre数组保存该节点的前驱节点,每一次更新路径都更新一下该节点的前驱节点,最后递归输出最短路。
细节:有数据范围:1≤m≤1e5,1≤w≤1e6可得,最长路径为1e11,所以需要使用LL
因为LL是八个字节,所以INF=0x3f3f3f3f3f3f3f3fll,注意最后有个ll
解法1:spfa(优先考虑)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
const int N = 100010, M = 200010, INF = 0x3f3f3f3f3f3f3f3fll;
int h[N], e[M], w[M], ne[M], idx;
int n, m, pre[N], pp;
LL dist[N];
bool st[N];
void add(int a, int b, int c)
{
w[idx] = c;
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
int spfa()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
queue<int> q;
q.push(1);
st[1] = true;
while(q.size())
{
int t = q.front();
q.pop();
st[t] = false;
for(int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if(dist[j] > dist[t] + w[i])
{
dist[j] = dist[t] + w[i];
pre[j] = t; //被更新
if(!st[j])
{
st[j] = true;
q.push(j);
}
}
}
}
return dist[n];
}
void out(int x)
{
if(pre[x] == -1)
{
cout << x;
return ;
}
out(pre[x]);
cout << " " << x;
return ;
}
int main()
{
memset(h, -1, sizeof h);
memset(pre, -1, sizeof pre);
cin >> n >> m;
for(int i = 0; i < m; i ++ )
{
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
add(b, a, c);
}
LL t = spfa();
if(t == INF) cout << -1 << endl;
else out(n);
return 0;
}
解法2:dijkstra
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
typedef pair<LL, int> PII;
const int N = 100010, M = 200010;
const LL INF = 0x3f3f3f3f3f3f3f3fll;
int n, m, pre[N];
int h[N], e[M], ne[M], w[M], idx;
bool st[N];
LL dist[N];
void add(int a, int b, int c)
{
w[idx] = c;
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
int heap_djikstra()
{
memset(dist, 0x3f, sizeof dist);
priority_queue<PII, vector<PII>, greater<PII> > heap;
heap.push({0, 1});
dist[1] = 0;
while(heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second;
LL distance = t.first;
if(st[ver]) continue;
st[ver] = true;
for(int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if(dist[j] > distance + w[i])
{
pre[j] = ver; //被更新
dist[j] = distance + w[i];
heap.push({dist[j], j});
}
}
}
if(dist[n] == INF) return -1;
return 0;
}
void out(int x) //递归输出最短路径,行尾无空格
{
if(pre[x] == -1)
{
cout << x;
return ;
}
out(pre[x]);
cout << " " << x;
return ;
}
int main()
{
memset(h, -1, sizeof h);
memset(pre, -1, sizeof pre);
cin >> n >> m;
while (m -- )
{
int a, b, c;
cin >> a >> b >> c;
add(a, b, c); add(b, a, c); //无向图
}
int t = heap_djikstra();
if(t == -1) puts("-1");
else out(n);
return 0;
}
应用: