# 最短路徑
:::info
有向無向皆可
:::
dijkstra
---
* 邊的權重不能為負
* 有n個點,設s為起點,$dis[v]$代表s到v的最點距離,$weight[a][b]$為a到b的權重,$done[v]=1$代表點v已走過, $parent[v]$是v的上一個點
* $dis[s]=0$,其餘為無限大
* done皆為0
* **步驟:**
1. 從沒走過的點中,找一個點x其$dis[x]$最小的,設done[x]=1,所以一開始x就是起點s
* 用priority_queue找dis[x]最小的,每次找最小又還沒走過的點,所以每次push{dis[u], u},pop要檢查done[x]是否為1
2. 對於每個x連到的點y,做$dis[y]=min(dis[y], dis[x]+weight[x][y])$
3. 重複 1.
* $O(V+ElogV)$
```cpp=
#define EB emplace_back
#define PII pair<int,int>
#define F first
#define S second
#define NL "\n"
using namespace std;
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
int n, m, u, v, w;
cin>>n>>m;
vector<vector<PII>> gh(n, vector<PII>());
rep(0,m){
cin>>u>>v>>w;
gh[u].EB(make_pair(v, w));
gh[v].EB(make_pair(u, w));
//doesn't matter if there's multiple line between two nodes, the algorithm will take the least one
}
//init
vector<int> done(n, 0);
vector<int> parent(n);
vector<int> dis(n, INT_MAX);
dis[0]=0; //default dis[s] is 0
priority_queue<PII, vector<PII>, greater<PII>> pq;
pq.push({dis[0], 0});
while(!pq.empty()){
PII x=pq.top();
pq.pop();
if(done[x.S]) continue;
done[x.S]=1;
for(auto a:gh[x.S]){
if(done[a.F]) continue; //not necessary
if(dis[x.S]+a.S<dis[a.F]){
dis[a.F]=dis[x.S]+a.S;
parent[a.F]=x.S;
pq.push({dis[a.F], a.F});
}
}
}
}
```
bellman ford
---
floyd warshall
---
* 動態規劃:對於dis[i][j],枚舉i~j的中點k
* 可用於權重為負值的情況,但不能有負環(可偵測負環)
* **找出所有點對的距離**
```cpp=
for(int k = 1; k <= n; k++){
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
dp[i][j]=min(dp[i][j], dp[i][k]+dp[k][j]);
}
}
}
```