學習記錄:Dijstra最短路
阿新 • • 發佈:2020-08-05
目錄
學習記錄:Dijstra最短路
其實Dijstra早學過,這次主要寫點用鄰接表和堆優化的東西
想法
Dijstra的想法其實很簡單,維護一個已經達到最短路線的點的集合即可。
從出發點開始,找到距離出發點最近的那個點加入集合,重複此步驟直至所有點都加入集合即可。
原因很簡單,設出發點為\(s\),距離\(s\)最近的點是\(i\),\(Dis[i]<Dis[其他點]+其他點到點i的距離\),因此最近的點就加入集合了。
鄰接矩陣實現的Dijstra
最簡單的Dij,但是過不了[洛谷弱化版的模板題][ https://www.luogu.com.cn/problem/P3371],空間佔用大,但是方便理解Dij的思路
int Map[maxn][maxn]; int vis[maxn]; ll dis[maxn]; int n, m, s; void Dij() { for (int i = 1; i <= n; i++) dis[i] = Map[s][i]; dis[s] = 0; vis[s] = 1; for (int j = 1; j <= n; j++) { int flag = 0; for (int i = 1; i <= n; i++) if (!vis[i] && (dis[i] < dis[flag] || flag == 0)) flag = i; vis[flag] = 1; for (int i = 1; i <= n; i++) if (!vis[i]) dis[i] = min(dis[i], dis[flag] + Map[flag][i]); } } int main() { cin >> n >> m >> s; while (m--) { int u, v, w; cin >> u >> v >> w; Map[u][v] = min(w, Map[u][v]);//洛谷的資料最坑的就是有重邊... } Dij(); for (int i = 1; i <= n; i++) cout << dis[i] << ' '; return 0; }
鄰接表實現的Dijstra
這樣就可以過模板題了。用的vector實現。
struct node { int to, val; node(int to, int val) : to(to), val(val) {} }; ll n, m, s; ll dis[maxn]; int vis[maxn]; vector<node> Map[maxn]; void Dij() { for (int i = 0; i <= n; i++) dis[i] = INF; dis[s] = 0;//這裡沒有初始化dis陣列,是因為接下來的迴圈可以直接初始化 for (int k = 0; k < n; k++) { int kk = 0; for (int i = 1; i <= n; i++) if (!vis[i] && dis[i] < dis[kk]) kk = i; vis[kk] = 1; for (int i = 0; i < Map[kk].size(); i++) if (dis[Map[kk][i].to] > dis[kk] + Map[kk][i].val) dis[Map[kk][i].to] = dis[kk] + Map[kk][i].val; } } int main() { cin >> n >> m >> s; for (int i = 0, a, b, c; i < m; i++) { cin >> a >> b >> c; Map[a].push_back(node(b, c)); } Dij(); for (int i = 1; i <= n; i++) cout << dis[i] << ' '; return 0; }
堆優化的Dijstra
struct node
{
int to, val;
node(int to, int val) : to(to), val(val) {}
};
int n, m, s;
vector<node> Map[maxn];
int vis[maxn], dis[maxn];
typedef pair<int, int> P;
void Dij()
{
priority_queue<P, vector<P>, greater<P>> q;
MS(dis, INF);
dis[s] = 0;
q.push(P(0, s));
while (!q.empty())
{
P p = q.top();
q.pop();
int index = p.second;
if (dis[index] < p.first)
continue;
for (int i = 0; i < Map[index].size(); i++)
{
node e = Map[index][i];
if (dis[e.to] > dis[index] + e.val)
{
dis[e.to] = dis[index] + e.val;
q.push(P(dis[e.to], e.to));
}
}
}
}
int main()
{
cin >> n >> m >> s;
for (int i = 1, x, y, z; i <= m; i++)
{
cin >> x >> y >> z;
Map[x].push_back(node(y, z));
}
Dij();
for (int i = 1; i <= n; i++)
cout << dis[i] << ' ';
return 0;
}