1. 程式人生 > >【演算法】單源最短路——Dijkstra

【演算法】單源最短路——Dijkstra

對於固定起點的最短路演算法,我們稱之為單源最短路演算法。單源最短路演算法很多,最常見的就是dijkstra演算法。

dijkstra主要用的是一種貪心的思想,就是說如果i...s...t...j是最短路,那麼i和j之間的任意兩點s,t之間也一定是最短路,非常好證,如果s,t之間不是最短路,那麼必然存在最短路,那麼i到j也不是最短路造成了矛盾。

而dijkstra就是運用這樣的思想,把起點首先放進一個集合S中,其他的點在另一個集合中,每次取起點經過集合S中的點可達的最短路的點,加入到集合S中,並且根據新加入的店重新整理一遍最短路。直到所有的點都在集合S中。


如上圖,假設以1為起點,dis[i]為起點到i點的最短距離,如果沒法直達則為INF

第一次:S中只有1,那麼1能直達的點有2,3,取路徑最短的3加入S,並更新一遍dis,發現6可達,dis[6] = 20;

第二次:S中有1,3,可達的有2,6,取2,則4,5可達,dis[4] = 21,dis[5] = 10;

第三次:S中有1,2,3,可達的有4,5,6,取5,到4多了新路徑且比原來近,更新dis[4] = 13;

第四次:S中有1,2,3,5,可達的有4,6,取4,到6多了新路徑且比原來近,更新dis[6] = 15;

第五次:S中有1,2,3,4,5,可達的有6,只有6不在S中,取6,不更新,完成演算法

要注意的是外圍迴圈是除了起點外的點數,如果多一次,pos會無法賦值因為所有的點都遍歷過了,造成變數沒有初始化而程式崩潰。

程式碼如下:

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 10;
int map[maxn][maxn], dis[maxn];
int n;                                                         //點數

void init()
{
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			map[i][j] = 0x3f3f3f;
	memset(dis, 0, sizeof(dis));
}
void dijkstra(int v0)
{
	for (int i = 1; i <= n; i++)
		dis[i] = map[v0][i];
	map[v0][v0] = 0;
	for (int i = 1; i < n; i++)                                //注意迴圈的次數,如果到n,最後一次所有的map[i][i]都是0,pos找不到值會崩潰,如果初始化為0則dis[i]最後全是0(dis[0] = 0)
	{
		int min_dis = 0x3f3f3f3f,pos;
		for (int j =1; j <= n; j++)
		{
			if (map[j][j] && dis[j] < min_dis)                 //遍歷所有點找到距離v0最小的點,記錄下距離,並將其加入已計算的集合,將其編號用pos記錄下來
				min_dis = dis[pos = j];
		}
		map[pos][pos] = 0;                                     //用map[i][i]來表示某個點是否被訪問過,節省空間

		for (int j = 1; j <= n; j++)
		{
			dis[j] = min(dis[j], dis[pos] + map[pos][j]);      //用新新增的點來更新一邊dis
		}
	}
}

int main()
{
	freopen("input.txt", "r", stdin);
	int m,u,v,w,target;
	scanf("%d%d", &n,&m);
	init();
	while (m--)
	{
		scanf("%d%d%d", &u, &v, &w);
		map[u][v] = map[v][u] = w;
	}
	scanf("%d", &target);
	dijkstra(target);
	for (int i = 1; i <= n; i++)
	{
		printf("%d : %d\n", i, dis[i]);
	}
	return 0;
}
但要注意的是,dijkstra不能計算含有負權的圖的最短路,因為一直加負數始終會比原來的小。

相關推薦

演算法短路——Dijkstra

對於固定起點的最短路演算法,我們稱之為單源最短路演算法。單源最短路演算法很多,最常見的就是dijkstra演算法。 dijkstra主要用的是一種貪心的思想,就是說如果i...s...t...j是最短路,那麼i和j之間的任意兩點s,t之間也一定是最短路,非常好證,如果s,t

[短路/線段樹大法優化DIJ] 模板短路徑(標準版)

洛谷原題 這題我自己看了STL優先佇列後試了試優化DIJ演算法,但我這個菜比只有32分... 還是老老實實用線段樹吧! 自己寫的程式,反正AC了,線段樹大法好! 具體見程式碼 #include<bits/stdc++.h> using namespace std; long lon

#dijkstra+zkw線段樹#洛谷 4779 洛谷 1339 模板短路徑(標準版)熱浪

分析 首先為什麼要說這種方法呢,因為根據模板,zkw線段樹優化比STL堆快了一倍,所以說在此推薦我的熱浪題解 程式碼 #include <cstdio> #include <cctype> #include <algorithm> #

短路徑快速演算法(spfa)的python3.x實現

單源最短路徑快速演算法(spfa)的python3.x實現 0. 寫在最前面 最近比較忙呢,寫的比較少了。抽空寫了一下這篇文件,簡陋勿噴~(後面準備做個演算法包,包括基礎的資料結構和演算法,感覺任重而道遠) 1. SPFA的簡介[1] SPFA(

演算法基礎6短路徑——詳解Bellman-Ford、迪傑斯特拉演算法

首先我們構造研究物件:計算從V0開始到所有節點的最短路徑1、dijkstra,D演算法首先我們將需要計算最小路徑的入口點的Cost複製到一個D數組裡。(鄰接矩陣對應的行)我們知道第一個節點到達的各個頂點所需的花費(路程)(無法到達花費是正無窮)找到最近的那個點。存下來(如果我

P3371 模板短路徑

logs alt front 最短路徑 ios num return struct 有向圖 題目描述 如題,給出一個有向圖,請輸出從某一點出發到所有點的最短路徑長度。 輸入輸出格式 輸入格式: 第一行包含三個整數N、M、S,分別表示點的個數、有向邊的個數

20171109Luogu P3371 模板短路徑--SPFA

else 輸入 所有 rom scanf node 時空 void edge 題目描述 如題,給出一個有向圖,請輸出從某一點出發到所有點的最短路徑長度。 輸入輸出格式 輸入格式: 第一行包含三個整數N、M、S,分別表示點的個數、有向邊的個數、出發點的編號。 接

短路-dijkstra的算法

strong com 初始化 csdn ostream 最短距離 長度 main turn 迪傑斯特拉算法用於求解單源最短路問題,能求解出從一個點出發到剩余所有節點的最短距離。 原理: 使用貪心選擇,將全部節點分為兩部分,已經找出最短路徑的點和沒有為找出最短路徑的點,初

模板短路徑——Floyd

表示 而且 鄰接 正是 內容 tle code spa 可能 抱歉這幾天 晚上一直認真 (頹廢)打模擬賽 一直沒寫博客 然後今天學了最短路 然後 馬上過來碼一下 以下內容 有的是搬得那些大佬們得博客 也謝謝他們 1.Floyd 感覺

luogu P4779 模板短路徑(標準版)

-o2 struct call 哈哈 poi fun fin hole char 線段樹優化dij 哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈 我可能是個智障 // luogu-judger-enable-o2 #pragma GCC diagnostic error "-

短路(dijkstra)模板

#include<stdio.h> #include<algorithm> #include<iostream> #include<string.h> const int inf = 9999999; int minn,flag; int main(v

[洛谷3371&&4779]模板短路徑

題目 https://www.luogu.org/problemnew/show/P3371 [P3371 【模板】單源最短路徑(弱化版)] https://www.luogu.org/problemnew/show/P4779 P4779 【模板】單源最短路徑(標準版)

題解 P3371 模板短路徑(弱化版)

一個story: 2018.10.3,晚上,在與我校是競爭關係的學校的機房(去一起集訓)訓練。 我:(頹) 對方教練:(走過來) 我:(趕快開始假裝研究SPFA) 對方教練:這是?最短路? 我:是啊是啊(瘋狂掩飾尷尬) 對方:這是SPFA? 我:是啊是啊(瘋狂掩

Floyd演算法短路(圖,資料結構)

Floyd演算法思路:計算某點到其餘各點的距離,可先求該點到其中一個點的距離,其他各點類似。假設求i點到j點的距離,跳點為空時,最短距離就是i到j的最短距離,跳點為1時,最短距離為D[i][j] = min{D[i][j],D[i][1]+D[1][j]},跳點為1和2時,最短距離為D[i][j]=min{D

LG4779 模板短路徑(標準版)

題意 給定一個 \(N\) 個點,\(M\) 條有向邊的帶非負權圖,請你計算從 \(S\) 出發,到每個點的距離。 資料保證你能從 \(S\) 出發到任意點。 \(1≤N≤100000\); \(1≤M≤200000\); 分析 可以斐波那契堆。 程式碼 #include<iostrea

洛谷 P4779 模板短路徑(標準版) 題解

題目來源: 題目描述: 題目背景 狗哥做爛了最短路,突然機智的考了Bosh一道,沒想到把Bosh考住了...你能幫Bosh解決嗎? 他會給你100000000000000000000000000000000000%10金幣w 題目描述 給定n個點的帶權有向

1062 短路 Dijkstra

傳送門題目大意: 有n中個人, 每個人手中都有一種物品, 可以直接購買, 也可以通過另外幾種物品中的一種加一部分錢進行交換, 跟著幾個人交換是, 他們中最高等級的人與最低等級的人相差不能超過m. 問

P3371 模板短路徑(弱化版)

pre urn mes enable 路徑 gdi name div int // luogu-judger-enable-o2 #include<cstdio> #include<iostream> #include<algorit

資料結構短路徑 Dijkstra演算法

單源最短路徑問題是指:對於給定的有向網路G=(V,E),求原點V0到其他頂點的最短路徑。 按照長度遞增的順序逐步產生最短路徑的方法,稱為Dijkstra演算法。 該演算法的基本思想: 把圖中的所有頂點分成兩組,第一組包括已確定最短路徑的頂點,初始時只含有一個源點,記為集合S;第

演算法導論短路徑之Dijkstra演算法

        Dijkstra演算法解決了有向圖上帶正權值的單源最短路徑問題,其執行時間要比Bellman-Ford演算法低,但適用範圍比Bellman-Ford演算法窄。 迪傑斯特拉提出的按路徑長度遞增次序來產生源點到各頂點的最短路徑的演算法思想是:對有n個頂點的有向連