如何用Dijkstra算法輸出最短路徑

方法:

方法就是在進行鬆弛操做的時候,若是能經過某個點進行鬆弛操做,就把這個點的出去的那個點的前驅設置爲這個點node

正確性:

由於全部點都會被至少鬆弛到一次,若是不進行鬆弛操做,那麼這個點的前驅就必定仍是原來的前驅。這個是Dijkstra算法的一個很神奇的地方,若是能進行鬆弛操做,說明若是要經過最短路到達這個點,就只能修改這個點的前驅。ios

模板題目來源:

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;
}
相關文章
相關標籤/搜索