acwing 849 Dijkstra求最短路

2022-09-29 15:39:17 字數 4220 閱讀 5647

目錄演算法求解

堆優化演算法

參考文章

題目傳送門

給定乙個 n 個點 m 條邊的有向圖,圖中可能存在重邊和自環,所有邊權均為正值。

請你求出 1 號點到 n 號點的最短距離,如果無法從 1 號點走到n 號點,則輸出 −1。

輸入格式

第一行包含整數 n 和 m。

接下來 m 行每行包含三個整數 x,y,z,表示存在一條從點 x 到點 y 的有向邊,邊長為 z。

輸出格式

輸出乙個整數,表示 1 號點到 n 號點的最短距離。

如果路徑不存在,則輸出 −1。

資料範圍

1≤n≤500

1≤m≤105

圖中涉及邊長均不超過10000。

輸入樣例:

3 3

1 2 2

2 3 1

1 3 4

輸出樣例:
3
模板

注意初始化的時候,初始化為正無窮

迴圈n-1次,然後每次確定乙個點的最短距離

#include#include#include#includeusing namespace std;

const int inf = 0x3f3f3f3f;

const int n = 510;

int g[n][n]; // 用鄰接矩陣存圖

int st[n];// st[i] = true 表示i點的最短距離已經確定了

int dist[n]; // 存從1到每個點的最短距離

int n, m;

// 返回從1到n的最短距離

int dijkstra()

if(dist[n] == inf) return -1;

else return dist[n];

} int main()

int t = dijkstra();

printf("%d\n", t);

return 0;

}

#include#include#include#include#includeusing namespace std;

typedef pairpii;

const int n = 150010;

const int inf = 0x3f3f3f3f;

int dist[n]; // 從1到每個點的最短距離

bool st[n]; // 每個點是否出現過

int n, m;

// 乙個點和邊權

struct ver

; vectorh[n];

// a->b 邊權是w

void add(int a, int b, int w)

// 定義圖

int dijkstra()

); // push到堆裡的是乙個pair,第乙個是到該點的最短距離,第二個是該點的編號,

// 因為優先佇列按照第乙個排序

// 每次不continue的時候確定乙個點的最小距離

while(heap.size())

); //dist[j]會被放入多次,會有冗餘,只需要取最小的那個就行

}} st[ver] = true; // 確定了該點的最小距離

} if(dist[n] == inf) return -1;

else return dist[n];

}int main()

int t = dijkstra();

printf("%d\n", t);

return 0;

}

y總**

#include #include #include #include using namespace std;

typedef pairpii;

const int n = 1e6 + 10;

int n, m;

int h[n], w[n], e[n], ne[n], idx;

int dist[n];

bool st[n];

void add(int a, int b, int c)

int dijkstra()

); while (heap.size()));}

}}

if (dist[n] == 0x3f3f3f3f) return -1;

return dist[n];

}int main()

cout << dijkstra() << endl;

return 0;

}

樸素dijkstra與堆優化dijkstra總結,初學演算法如有錯誤還望指正。

dijkstra

樸素版dijkstra適合稠密圖

思路集合s為已經確定最短路徑的點集。

初始化距離

一號結點的距離為零,其他結點的距離設為無窮大(看具體的題)。

迴圈n次,每一次將集合s之外距離最短x的點加入到s中去(這裡的距離最短指的是距離1號點最近。點x的路徑一定最短,基於貪心,嚴格證明待看)。然後用點x更新x鄰接點的距離。

時間複雜度分析

尋找路徑最短的點:o(n^2)

加入集合s:o(n)

更新距離:o(m)

所以總的時間複雜度為o(n^2)

具體問題

稠密圖用鄰接矩陣存。

#include#include#include#includeusing namespace std;

const int n = 510, m = 10010; // y總增大資料範圍了吧m改到100010就能ac了

int g[n][n], dist[n];

bool visited[n];

int n, m;

int dijkstra()

visited[t] = true;

for(int j = 1; j <= n; j++)

dist[j] = min(dist[j], dist[t] + g[t][j]);

}if(dist[n] == 0x3f3f3f3f) return -1;

return dist[n];

}int main()

cout << dijkstra() << endl;

return 0;

}

堆優化版dijkstra適合稀疏圖

思路堆優化版的dijkstra是對樸素版dijkstra進行了優化,在樸素版dijkstra中時間複雜度最高的尋找距離最短的點o(n^2)可以使用最小堆優化。

一號點的距離初始化為零,其他點初始化成無窮大。

將一號點放入堆中。

不斷迴圈,直到堆空。每一次迴圈中執行的操作為:

彈出堆頂(與樸素版diijkstra找到s外距離最短的點相同,並標記該點的最短路徑已經確定)。

用該點更新臨界點的距離,若更新成功就加入到堆中。

時間複雜度分析

尋找路徑最短的點:o(n)

#include#include#includeusing namespace std;

typedef pairpii;

const int n = 100010; // 把n改為150010就能ac

// 稀疏圖用鄰接表來存

int h[n], e[n], ne[n], idx;

int w[n]; // 用來存權重

int dist[n];

bool st[n]; // 如果為true說明這個點的最短路徑已經確定

int n, m;

void add(int x, int y, int c)

int dijkstra()

); // 這個順序不能倒,pair排序時是先根據first,再根據second,這裡顯然要根據距離排序

while(heap.size()));}

}}

if(dist[n] == 0x3f3f3f3f) return -1;

else return dist[n];

}int main()

cout << dijkstra() << endl;

return 0;

}

849 Dijkstra求最短路 I

給定乙個n個點m條邊的有向圖,圖中可能存在重邊和自環,所有邊權均為正值。請你求出1號點到n號點的最短距離,如果無法從1號點走到n號點,則輸出 1。輸入格式 第一行包含整數n和m。接下來m行每行包含三個整數x,y,z,表示存在一條從點x到點y的有向邊,邊長為z。輸出格式 輸出乙個整數,表示1號點到n號...

Dijkstra求最短路

題目鏈結 給定乙個n個點m條邊的有向圖,圖中可能存在重邊和自環,所有邊權均為正值。請你求出1號點到n號點的最短距離,如果無法從1號點走到n號點,則輸出 1。輸入格式 第一行包含整數n和m。接下來m行每行包含三個整數x,y,z,表示存在一條從點x到點y的有向邊,邊長為z。輸出格式 輸出乙個整數,表示1...

Dijkstra求最短路

題目鏈結 給定乙個n個點m條邊的有向圖,圖中可能存在重邊和自環,所有邊權均為非負值。請你求出1號點到n號點的最短距離,如果無法從1號點走到n號點,則輸出 1。輸入格式 第一行包含整數n和m。接下來m行每行包含三個整數x,y,z,表示存在一條從點x到點y的有向邊,邊長為z。輸出格式 輸出乙個整數,表示...