1. 程式人生 > 其它 >acwing 849. Dijkstra求最短路 I

acwing 849. Dijkstra求最短路 I

目錄

題目傳送門

題目描述

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

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

輸入格式

第一行包含整數 nn 和 mm。

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

輸出格式

輸出一個整數,表示 11 號點到 nn 號點的最短距離。

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

資料範圍

1≤n≤5001≤n≤500,
1≤m≤1051≤m≤105,
圖中涉及邊長均不超過10000。

輸入樣例:

3 3
1 2 2
2 3 1
1 3 4

輸出樣例:

3

演算法求解

分析

模板

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

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

程式碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using 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()
{
	// 初始化從1到所有點距離為正無窮 
	memset(dist, 0x3f, sizeof dist);
	dist[1] = 0;

	
	// 迴圈n-1次每次取未確定的點裡面距離最小的 
	for(int i = 0; i < n-1; i++)
	{
		// 從沒確定的點裡面選一個最小的值 t 
		int t = -1;
		for(int i = 1; i <= n; i++) 
			if(!st[i] && (t == -1 || dist[i] < dist[t]))
				t = i;
		
		// 跟新t指向節點的最短距離 
		for(int i = 1; i <= n; i++)
			// dist[i] = min(dist[i], dist[t] + g[t][i]);
			if(!st[i] && dist[i] > dist[t] + g[t][i])
				dist[i] = dist[t] + g[t][i]; 
		
		
		st[t] = true; //確定了一個點的最短距離 
	}
	
	if(dist[n] == INF)        return -1;
	else					  return dist[n];
} 

int main()
{
	// 初始化所有點之間邊權為無窮大 
	memset(g, 0x3f, sizeof g);
	 
	scanf("%d%d", &n, &m);
	while(m--)
	{
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		g[a][b] = min(g[a][b], c); // 有重邊的話選小的那個 
	}
	int t = dijkstra();
	
	printf("%d\n", t); 
	return 0;
}

時間複雜度

參考文章