# Summary of shortest path algorithm

Posted by podja on Mon, 20 Sep 2021 08:21:44 +0200

# Summary of shortest path algorithm

### 1.floyd full source shortest circuit (negative weight side can be solved, but negative weight circuit cannot be solved)

Core of the code: during the process from point i to point j, find out whether there is point K (k! = i & & K! = j) as the transfer point, so that the shortest circuit between point i and point j can be updated, so as to complete the code.

## Note: k should be placed in the outermost loop (essentially related to dynamic gauge state transfer), otherwise some magical data points will make mistakes!!!

```#include<bits/stdc++.h>
using namespace std;
#define N 200 / / basically the maximum data range

int f[N][N];//The shortest distance between two points
int main(){
int n, m;//n is the number of points and m is the number of edges
scanf("%d%d", &n, &m);
memset(f, 0x3f, sizeof(f));//Initialize to infinity
for(int i = 1; i <= n; ++ i)
f[i][i] = 0;//The distance from self to self is initialized to 0
for(int j = 1; j <= m; ++ m){
scanf("%d%d%d", &x, &y, &z);
if(z < f[x][y]) f[x][y] = f[y][x] = z;
}
for(int k = 1; k <= n; ++ k)//k must circulate in the outermost layer as a state of dynamic transfer
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= n; ++ j)
if(i != k && i != j && k != j && f[x][k] + f[k][y] < f[x][y]) f[x][y] = f[y][x] = f[x][k] + f[k][y];
f[a][b]mean a,b Shortest distance between two points
return 0;
}
```

### 2.dijikstra single source shortest circuit (negative weight edge cannot be solved)

The core of the code: if the relaxation operation can be realized, add the points to the priority queue, take out the points with the shortest distance from the starting point for expansion each time, and ensure that each point traverses all its adjacent points only once.

Here, the code is directly optimized with heap, because the dijikstra that is not optimized has little significance (high time complexity)

## Note: when pressing into the queue, the opposite number of blank holder weights should be. (the default is large root heap)

```#include<bits/stdc++.h>
using namespace std;
const int N = 1050;//Basic is the maximum data range
int dis[N];
bool vis[N];
vector<pair <int , int> >vec[N];
priority_queue<pair <int , int> >que;//Big root pile
void dijk(int x){
que.push(make_pair(0, x));
dis[x] = 0;
while(!que.empty()){
int u = que.top().second;
que.pop();
if(vis[u]) continue;
vis[u] = 1;
int len = vec[u].size();
for(int i = 0; i < len; ++ i){
int v = vec[u][i].first;
int w = vec[u][i].second;
if(dis[u] + w < dis[v]){
dis[v] = dis[u] + w;
que.push(make_pair(-dis[v], v));//Press
}
}
}
return ;
}
int main(){
int x, y, v;
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; ++ i){
scanf("%d%d%d", &x, &y, &v);
vec[x].push_back(make_pair(y, v));
vec[y].push_back(make_pair(x, v));
}
int center;
scanf("%d", &center);
memset(dis, 63, sizeof(dis));
dijikstra(center);//Find the shortest path of each point starting from the center and store it in the dis array
printf("%d", dis[Target point]);
return 0;
}
```

### 3. Bellman Ford single source shortest path (can solve the negative weight edge, can not solve the negative ring, but can judge the negative ring)

Code core: run n cycles, and the distance between the first and last points of m edges each time. If it can be updated, it will be updated in time.

```#include<bits/stdc++.h>
using namespace std;
#define N 3050

struct Edge{
int u, v;
int w;
}edge[N];//Structure array is used to store edges
int dis[N];
int main(){
int U, V;//start and finish
scanf("%d%d", &U, &V);
memset(dis, 63, sizeof(dis));
dis[U] = 0;//initialization
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; ++ i)
scanf("%d%d%d", &edge[i].u, &edge[i].v, edge[i].w);
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= m; ++ j){
if(dis[edge[j].u] + edge[j].w < dis[edge[j].v])
dis[edge[j].v] = dis[edge[j].u] + edge[j].w;
if(dis[edge[j].v] + edge[j].w < dis[edge[j].u])
dis[edge[j].u] = dis[edge[j].v] + edge[j].w;
}
for(int j = 1; j <= m; ++ j)
if(dis[edge[j].u] + edge[j].w < dis[edge[j].v] || dis[edge[j].v] + edge[j].w < dis[edge[j].u])
printf("There is a negative ring!!!")
printf("%d", dis[V]);
return 0;
}
```

### 4.spfa finds the shortest path of a single source (it can solve the negative weight edge, but it can not solve the negative loop, so it can judge the negative loop)

Code core: with the bellman Ford algorithm optimized by queue, the redundant loop is omitted, and the operation efficiency is greatly high.

```#include<bits/stdc++.h>
using namespace std;
const int N = 200010;

int n, m;
vector<pair<int, int> >vec[N];
queue<pair<int, int> >que;

int dis[N], d[N];//d[N] is the number of steps required to take the shortest path to reach a certain point
bool vis[N];
int spfa(int s)
{
memset(dis, 63, sizeof(dis));
dis[s] = 0;
vis[s] = 1;
que.push(make_pair(0, s));
while(!que.empty())
{
int u = que.front().second;
vis[u] = 0;
que.pop();
for(int i = 0; i < vec[u].size(); ++i){
int v = vec[u][i].first;
int w = vec[u][i].second;
if(dis[u] + w < dis[v]){
dis[v] = dis[u] + w;
d[v] = d[u] + 1;
if(d[v] >= n) return 1;//If there is no negative loop, take the shortest path to reach a point and use n-1 edges at most
if(!vis[v]){
vis[v] = 1;
que.push(make_pair(dis[v], v));
}
}
}
}
return 0;
}
int main()
{
scanf("%d%d", &n, &m);
int x, y, z;
for(int i = 1; i <= m; ++i){
scanf("%d%d%d", &x, &y, &z);
vec[x].push_back(make_pair(y, z));
vec[y].push_back(make_pair(x, z));
}
int U, V;//U: Start V: end
scanf("%d%d", &U, &V);
int judge = spfa(U);
if(judge == 1) puts("There is a negative ring!!!")
else	printf("%d", dis[V]);
return 0;
}
```

### 5.johnson all source shortest circuit (negative weight edge can be solved, negative loop can be judged if negative loop cannot be solved)

Code key: the combination of Bellman Ford and dijikstra is better than spfa algorithm for n times in a large data range.

Reprint [Los Angeles Daily #242] Johnson's learning notes on all source shortest path algorithm

Exercise: P5905 [template] Johnson all source shortest circuit

## It is suggested to read the notes first and then do the problem. Here is the solution to this problem

```#include<bits/stdc++.h>
using namespace std;
#define N 3005

int h[N], vis[N];
long long dis[N];
struct Edge{
int u, v;
int w;
}edge[N * 2];//Structure array is used to store edges
vector<pair <int , int> >vec[N];
priority_queue<pair <long long , int> >que;//Big root pile
void dijikstra(int x){
memset(vis, 0, sizeof(vis));
que.push(make_pair(0, x));
dis[x] = 0;
while(!que.empty()){
int u = que.top().second;
que.pop();
if(vis[u]) continue;
vis[u] = 1;
int len = vec[u].size();
for(int i = 0; i < len; ++ i){
int v = vec[u][i].first;
int w = vec[u][i].second;
if(dis[u] + w < dis[v]){
dis[v] = dis[u] + w;
que.push(make_pair(-dis[v], v));
}
}
}
return ;
}
int main(){
int n, m;
scanf("%d%d", &n, &m);
int x, y, z;
for(int i = 1; i <= m; ++ i){
scanf("%d%d%d", &x, &y, &z);
edge[i].u = x;
edge[i].v = y;
edge[i].w = z;
}
for(int i = 0; i <= n; ++ i)
for(int j = 1; j <= m; ++ j){
if(h[edge[j].u] + edge[j].w < h[edge[j].v])
h[edge[j].v] = h[edge[j].u] + edge[j].w;
}
for(int j = 1; j <= m; ++ j)
if(h[edge[j].u] + edge[j].w < h[edge[j].v]){
puts("-1");
return 0;
}
for(int i = 1; i <= m; ++ i)
vec[edge[i].u].push_back(make_pair(edge[i].v, edge[i].w + h[edge[i].u] - h[edge[i].v]));
for(int i = 1; i <= n; ++ i)
dis[i] = 1e9;
for(int i = 1; i <= n; ++ i){
dijikstra(i);
long long tot = 0;
for(int j = 1; j <= n; ++ j){
if(dis[j] == 1e9) tot += j * 1e9;
else tot += j * (dis[j] + h[j] - h[i]);
dis[j] = 1e9;
}
printf("%lld\n", tot);
}
return 0;
}
```

# The above is the summary of the shortest path algorithm. There must still be some errors. You are welcome to criticize and correct. It's not easy to sort out. If it brings you some help, I hope you can like forwarding, thank you!!!

Topics: Algorithm