方法:
方法就是在進行松弛操作的時候,如果能通過某個點進行松弛操作,就把這個點的出去的那個點的前驅設置為這個點
正確性:
因為所有點都會被至少松弛到一次,如果不進行松弛操作,那么這個點的前驅就一定還是原來的前驅。這個是Dijkstra算法的一個很神奇的地方,如果能進行松弛操作,說明如果要通過最短路到達這個點,就只能修改這個點的前驅。
模板題目來源:
https://www.luogu.org/problemnew/show/CF20C
代碼:
#include <iostream>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5+5;
const long long INF = 9223372036854775806;
int n,m;
int vis[N];
int pre[N];
long long dis[N];
struct node{
int u;
long long w;
};
vector <int> ans;
vector <node> graph[N];
priority_queue <pair<long long,long long>,vector <pair<long long,long long> >,greater <pair<long long,long long> > > q;
void add(int x,int y,long long z) //雙向圖
{
node temp;
temp.u=y;
temp.w=z;
graph[x].push_back(temp);
temp.u=x;
graph[y].push_back(temp);
}
void Dijkstra(int x)
{
while(!q.empty()){
pair <long long,long long> temp;
temp=q.top();
q.pop();
if(vis[temp.second]!=0) continue;
vis[temp.second]++;
vector <node> :: iterator it;
for(it=graph[temp.second].begin();it!=graph[temp.second].end();it++)
{
if(vis[it->u]!=0) continue;
if(dis[it->u]>dis[temp.second]+(it->w))
{
dis[it->u]=dis[temp.second]+(it->w);
pre[it->u]=temp.second;
q.push(make_pair(dis[it->u],it->u));
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
int temp_x,temp_y;
long long temp_z;
for(int i=1;i<=m;i++)
{
scanf("%d%d%lld",&temp_x,&temp_y,&temp_z);
add(temp_x,temp_y,temp_z);
}
//初始化dis數組
for(int i=1;i<=n;i++) dis[i]=INF;
dis[1]=0;
q.push(make_pair(dis[1],1));
Dijkstra(1);
bool flag=false;
int x=n;
while(true)
{
if(x==1) flag=true;
ans.push_back(x);
x=pre[x];
if(x==0) break;
}
if(!flag)
printf("-1\n");
else
{
for(int i=(int)ans.size()-1;i>=0;i--)
printf("%d ",ans[i]);
printf("\n");
}
return 0;
}