目錄演算法求解
堆優化演算法
參考文章
題目傳送門
給定乙個 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)
具體問題
稠密圖用鄰接矩陣存。
堆優化版dijkstra適合稀疏圖#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中時間複雜度最高的尋找距離最短的點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。輸出格式 輸出乙個整數,表示...