最短路径算法笔记
最短路径算法主要包括 \(floyd\) 算法,\(dijkstra\) 算法, \(spfa\)算法
\(Floyd\) 算法
时间复杂度:\(O(n^3)\)
是用来求任意两个结点之间的最短路的。
复杂度比较高,但是常数小,容易实现(只有三个$ for $)。
适用于任何图,不管有向无向,边权正负,但是最短路必须存在。(不能有个负环)
代码模板
//floyd
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
g[i][j] = min(g[i][k] + g[k][j], g[i][j]);
\(spfa\) 算法
时间复杂度:一般 \(O(m)\), 最坏\(O(nm)\)。
\(SPFA\) 算法是求解单源最短路径问题的一种算法,由理查德·贝尔曼(Richard Bellman) 和 莱斯特·福特 创立的。有时候这种算法也被称为$ Moore-Bellman-Ford $算法。它的原理是对图进行V-1次松弛操作,得到所有可能的最短路径。其优于迪科斯彻算法的方面是边的权值可以为负数、实现简单,缺点是时间复杂度过高,高达 O(VE)。但算法可以进行若干种优化,提高了效率。可以判负环。
代码模板
void spfa(int u) {
memset(dis, 0x3f3f3f3f, sizeof dis);
queue<int> q;
/* 如果单纯判断负环则将所有点放入队列
for (int i = 1; i <= n; i++) {
q.push(i);
st[i] = 0;
}
必要时用超级源点
*/
dis[u] = 0;
st[u] = 1;
q.push(u);
while (q.size()) {
int u = q.front();
q.pop();
st[u] = 0;
for (auto t : v[u]) {
int e = t.first;
int w = t.second;
if (dis[e] > dis[u] + w) {
dis[e] = dis[u] + w;
cnt[e] = cnt[u] + 1;
//判环
if (cnt[e] >= n) {
cout << "Yes" << '\n';
return;
}
if (st[e] == 0) {
q.push(e);
st[e] = 1;
}
}
}
}
if (dis[n] <= 1e17)
cout << dis[n] << '\n';
else
cout << "impossible\n";
}
\(dijkstra\) 算法
时间复杂度:朴素版 \(O(n^2)\) 堆优化版 \(O(mlogn)\)。
$Dijkstra $算法由荷兰计算机科学家 E. W. Dijkstra 于 1956 年发现,1959 年公开发表。是一种求解 非负权图 上单源最短路径的算法。
代码模板
朴素版
void dijkstra(){
for(int i=1;i<=n;i++) dis[i]=1e18;
dis[1]=0;
for(int i=1;i<=n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(st[j]==0)
{
if(t==-1||dis[j]<dis[t]) t=j;
}
}
st[t]=1;
for(int j=1;j<=n;j++) dis[j]=min(dis[j],dis[t]+g[t][j]);
}
if(dis[n]==1e18) cout<<-1;
else cout<<dis[n];
}
堆优化版
void dijkstra() {
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
for (int i = 1; i <= n; i++)
dis[i] = 1e18;
memset(st, 0, sizeof(st));
dis[1] = 0;
q.push({0, 1});
while (q.size()) {
int u = q.top().second;
q.pop();
if (st[u] != 0)
continue;
st[u] = 1;
for (auto e : g[u]) {
int v = e.first; //点
int w = e.second; //权值
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
if (!st[v])
q.push({dis[v], v});
}
}
}
}
图论技巧
1.超级源点
2.超级汇点
讲解题目
1.P3371 【模板】单源最短路径(弱化版)
2.P4779 【模板】单源最短路径(标准版)
3.P3385 【模板】负环
4.B3647 【模板】Floyd
练习题目
1.P1744 采购特价商品
2.F - 这是个求最短路的题
3.P1821 [USACO07FEB] Cow Party S
4.P2299 Mzc和体委的争夺战