Dijkstra(堆優化)

Dijkstra 算法 (模板)【堆優化】

傳送門:

Dijkstra:建議先掌握原始版本

基本思路:用一個優先隊列,priority queue來保存點到點之間的距離,優先隊列自動把隊列裏的數據排序(這裏需要手動寫一個bool型函數來定義爲由大到小排序),枚舉各種可能的走法,包括當某兩點之間的路線爲無限大時,(所以可以自動處理重邊,而原始版本的不能)最後把最小的方案(即dis)輸出給d數組,標記一下,把剩餘的方案全部pop出去(相同出發點和目標點的情況下,所以代碼中有一句 if(vis[u]) continue;)。

注意:該模板已經使用STL裏的容器,如果對此不熟悉的讀者,請先自行百度搜索,我以後會貼出這方面的博客的。

OK,上代碼:

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cmath>
#include <algorithm>
#define INF 666666
using namespace std;
struct ed{int v,c;};//輸入數據時vector使用,u代表起始點,v代表目標點,c代表這條邊的權值; 
struct dn{int u,d;};//處理數據時使用,u代表目標點,d代表權值
vector<ed>g[10001];//注意,其實這裏就已經是一個二維數組了,因爲每一個vector數組就是一個一維數組
bool operator < (dn x,dn y){
	return x.d>y.d;
}                     //先出小的,就相當於普通算法中的遍歷找最小 
int vis[100001],d[100001],n,m,k;
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;++i)
	d[i]=INF;      //初始化d數組,默認與各點距離爲無限大 
	for(int i=1;i<=m;++i)
	{
		int u,v,c;
		scanf("%d%d%d",&u,&v,&c);
		g[u].push_back((ed){v,c});//輸入數據,這裏需注意題上給出的是單向路還是雙
	}//                                 單向路 不用判斷重邊,重邊的走法也考慮進了優先
	priority_queue<dn>q;//              隊列
	q.push((dn){k,0});//將起始點放入堆中 
	while(!q.empty()){
		int u=q.top().u,v;
		double dis=q.top().d;
		q.pop();//彈出 
		if(vis[u]) continue;//點u已經用過的話,就跳過 
		vis[u]=1;//否則標記爲1 
		d[u]=dis;//             struct dn{int u,d;}; 
		for(int i=0;i<g[u].size();i++)
		if(!vis[v=g[u][i].v])
		q.push((dn){v,d[u]+g[u][i].c}); //比較的事已經交給優先隊列q了,不必糾結了
	}//                                       哈哈哈
	for(int i=1;i<=n;++i)
	cout<<d[i]<<" ";
	return 0;
}

我的QQ:1206668472

END


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章