---
title: Dijkstra
tags: 演算法
---
## Dijkstra
### 解決單源最短路徑(不能負權)
#### 貪心思想
> 每次都找最短路徑加入集合 -> 再從最短的出發
> 直到沒有點
> 類 bfs 走訪(相鄰)
PSEUDOCODE:
```cpp
while ( 找到下一個點 ) :
找未訪問過(白點) 路徑最短
for(走訪 n 個點):
if (和當前點聯通):
更新路徑
```
### 優化
> 時間複雜度主要來自 **"提取最小值"**
> 可以使用 priority_queue 做優化
> 預設最大先排 要改成最小
> `priority_queue< mpair,vector<mpair> ,greater<mpair>>`
### 相關題目
UVa 534
(跳青蛙 -> 求單次(兩點間)最短)
```cpp=
#include <iostream>
#include <queue>
#include <cmath>
#include <iomanip>
using namespace std;
typedef pair<double,double> mpair;
class point{
public:
int x,y;
double distance(point b){ return sqrt( (b.x-x)*(b.x-x) + (b.y-y)*(b.y-y)); }
};
int main()
{
int n,r=1;
while(cin>>n,n){
vector<point> stone(n);
vector<vector<double> > graph(n,vector<double>(n));
priority_queue< mpair,vector<mpair> ,greater<mpair>> djk;
vector<bool> visted(n,0);
for(int i=0;i<n;i++)
cin>>stone[i].x>>stone[i].y;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
graph[i][j] = stone[i].distance(stone[j]);
djk.push({0,0});
double mindist = -1;
while(!djk.empty()){
int np = djk.top().second;
visted[np] = true;
mindist = max(djk.top().first,mindist);
if(np == 1)
break;
djk.pop();
for(int i = 0; i <n ;i++){
if(!visted[i]){
djk.push({graph[np][i],i});
}
}
}
printf("Scenario #%d\nFrog Distance = %.3f\n\n",r++,mindist);
}
return 0;
}
```