dijkstra算法
用于图论中求解最短路问题
思想是枚举距离初始点最近的点,并且把这个点相关的边更新,通过枚举n - 1次,我们就可以枚举出到达n的最短路径
不要忘记初始化dist[1] = 0
AcWing 849. Dijkstra求最短路 I - AcWing
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 500 + 10;
int n, m;
int g[N][N];
int dist[N]; //每个点到初始位置(1)的距离
bool st[N];
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for(int i = 0; i < n - 1; i++) //
{
int t = -1;
for(int j = 1; j <= n; j++) //从i ~ n 中选出距离初始位置最近的点
{
if(!st[j] && (t == -1 || dist[j] < dist[t]))
{
t = j;
}
}
for(int j = 1; j <= n; j++)
{ //用t(距离起点最短)更新其他点的距离
dist[j] = min(dist[j],dist[t] + g[t][j]);
}
st[t] = true;
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
int main()
{
cin>>n>>m;
memset(g, 0x3f, sizeof g);
for(int i = 0; i < m; i++)
{
int a, b, c;
cin>>a>>b>>c;
g[a][b] = min(g[a][b], c); //重边
}
cout<<dijkstra()<<endl;
}
Bellman-ford
思想:枚举一条边,并且更新这条边的dist, 循环k次,这样每次可行方案的边数是按循环次数来的。
但是要注意串联,当a 与 b 两条边相邻时,前面一条边a更新后,后面的b更新时会收到dist[a]的影响,这是不符合思想的,所以每次循环需要备份上一次dist的状态
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 500 + 10, M = 1e5 + 10;
int n, m, k;
int dist[N], backup[N];
struct Edge{
int a;
int b;
int c;
} edges[M];
void bellman_ford()
{
//将这距离初始化为正无穷
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for(int i = 0; i < k; i++)
{
//避免串联,也就是前面的点更新使后面的也更新了
memcpy(backup, dist, sizeof dist);
//对边进行循环
for(int j = 0; j < m; j++)
{
auto t = edges[j];
//这里注意要与当前边终点的最短距离,
//与该边未更新前的的最短距离加权值进行比较
dist[t.b] = min(dist[t.b], backup[t.a]+t.c);
}
}
}
int main()
{
cin>>n>>m>>k;
for(int i = 0; i < m; i++)
{
int a, b, c;
cin>>a>>b>>c;
edges[i] = {a, b, c}; //这里不必处理重边,因为每次选择最小的边
}
bellman_ford();
if(dist[n] > 0x3f3f3f3f / 2) puts("impossible");
else cout<<dist[n]<<endl;
return 0;
}
以上是个人觉得常用算法
下面是ACwing上大佬更精细的总结
\