1. 程式人生 > 其它 >【演算法練習】最短路徑

【演算法練習】最短路徑

技術標籤:演算法練習演算法dijkstrac++

Dijkstra演算法

輸入一個3*3的矩陣,輸出結果為2

#include<bits/stdc++.h> 
using std::cout;
using std::cin;
using std::endl;

const int N = 10001;
const int M = 10001;

int a[N],size; //當前圖中的邊數 ,首先初始化為0
int n, m;
int dis[N];  //當前最短路長 
bool vis[N];  //是否被標記,最好使用布林型別 

struct edge {
	int v, w, next;
//next:這條邊的下一條邊 edge() {} edge(int _v, int _w, int _next) { //建構函式 v = _v; w = _w; next = _next; } }e[M * 2]; //編號 void init() { memset(a, -1, sizeof(a)); //剛開始,預設-1,表示沒有任何一條邊從這個點連出 size = 0; } void insert(int u, int v, int w) // 插入一條邊 { e[size] = edge(v, w, a[u]); //邊連向的頂點編號,邊權,u連出的第一條邊 a[
u] = size++; //修改u連出的第一條邊的編號 } void insert2(int u, int v, int w) //插入一條無向邊 { insert(u, v, w); insert(v, u, w); } void dijkstra(int u) { memset(vis, false, sizeof(vis)); //memset 高效賦值 memset(dis, 0x3f, sizeof(dis)); //0x:十六進位制數 3f:實際的0011 1111 dis[u] = 0; for (int i = 0; i < n; i++) { int mind =
1000000, minj = -1; //當前沒標記過的點 的距離,編號 for (int j = 1; j <= n; j++) { //頂點編號從1開始 if (!vis[j] && dis[j] < mind) { // 判斷j 是否被標記 minj = j; mind = dis[j]; } } if (minj == -1) { // 沒有找到一個沒被標記過的點(不是連通圖) return; } vis[minj] = true; //訪問 minj //~j:j≠-1 for (int j = a[minj]; ~j; j = e[j].next) { int v = e[j].v; int w = e[j].w; if (!vis[j] && dis[minj] + w < dis[v]) { dis[v] = dis[minj] + w; //更新:到v的路徑長 } } } int cnt = 0; //被標記點的個數 for (int i = 1; i <= n; i++) { cnt += vis[i]; // vis裡要麼是1,要麼是0 } } int main() { init(); //初始化 邊陣列全為-1(表示無連線) size(圖中邊數)為0 int u, v, w; //u:頭點, v:尾點, w:邊權 cout << "" << endl; cin >> n >> m; while (m--) { cin >> u >> v >> w; insert2(u, v, w); } dijkstra(1); //設定:編號為1的點為起點 cout << dis[n] << endl; }

執行結果
在這裡插入圖片描述
執行時出現了一些小問題,vs報錯:size不明確。通過查詢得知:其實不提倡using namespace std; 的寫法,於是改成了

using std::cout;
using std::cin;
using std::endl;

SPFA演算法

當給定邊權值為負數時,無法使用Dijkstra演算法了。