# Dijkstra: the shortest circuit

#### brief introduction

Dijkstra algorithm is a typical shortest path algorithm, which is used to calculate the shortest path from one node to other nodes. The main feature of BFS is that it extends from the starting point to the end

Dijkstra cannot handle graphs with negative weights and loops

#### Algorithmic thought

1. Set the starting point as u, and introduce two sets S and U. the set S contains the points of the shortest path that have been found. The set u records the points of the shortest path that have not been found and the distance to the starting point

2. Initializes two sets. At the beginning of set S, there is only the starting point. At the beginning of set U, it is the distance from the starting point to other nodes (in detail, the distance from the starting point to itself is 0, and the distance from the point where the starting point is not directly connected is INF)

3. Find the point k with the shortest path from the U set, join the S set and delete the point from the U set

4. Traverse all nodes. If a node v makes the distance from u to k and then to v smaller than the current distance from u to v, update the corresponding distance in U

5. Cycle the above steps 3 and 4 until the end of traversal to get the shortest path from the starting point to other nodes

By simply analyzing the above ideas, we can get the following pseudo codes (Purple Book p359)

```Clear tags for all points in the tag array
Let d[s]=0, other d[i]=INF,s is the starting point
Cyclic n times {
Select the node k with the lowest d value from all unmarked nodes
Mark node k
For all edges (k,i) starting from K, update d[i]=min{d[i],d[k]+w(k,i)}
}
```

Where "update d[i]=min{d[i],d[k]+w(k,i)}" is called relaxation operation of edge (k,i)

#### code implementation

Time complexity O(V2), space complexity O(V2)

```#define INF 0x3f3f3f3f
const int N=1e3+10;
int d[N];   //Shortest path from storage start point to other nodes
bool vis[N]; //Displays whether the shortest path of the current node is updated
int n;  //Node number

void Dijkstra(int u){
memset(d,0x3f,sizeof(d));
memset(vis,0,sizeof(vis));
d[u]=0;
for(int i=1;i<=n;i++){
int k,m=INF;
for(int j=1;j<=n;j++)
if(!vis[j]&&d[j]<=m){
m=d[j];
k=j;
}
vis[k]=1;
for(int j=1;j<=n;j++) d[j]=min(d[j],d[k]+G[k][j]);
}
for(int i=1;i<=n;i++) printf("%d%c",d[i],i==n?'\n':' ');
}
```

In fact, we find that the idea of the above adjacency matrix is not consistent with the algorithm. But when we write the adjacency table, we find that the queue we use is equivalent to the set U

The first method is what I learned when I studied purple book. Instead of opening vector < edge > a set of vector < edge > two-dimensional dynamic arrays, I directly used one-dimensional vector < edge > edges to save all the edges, and then used two-dimensional dynamic array vector < int > G [n] to save the subscript in the edge array corresponding to each starting point. In fact, it's similar to a chain forward star, but there's no chain forward star to save space

The vector array holds the number of the edge. With the number, you can find the specific information of the edge from the edges array. Thus, "for all edges (k,i) starting from K, update d[i]" becomes "for (int i = 0; I < G [u]. Size(); I + +) to perform relaxation operations on edge edges(G[u][i]).". On the whole, each edge is checked exactly once, so the number of slack executions is exactly m times. So just try to find the "node K with the lowest unmarked D value"

Obviously, we need priority queue maintenance d[i], that is, the smaller the d[i], the earlier we should be out of the queue. Therefore, priority queue of minimum heap maintenance needs priority queue < int, vector < int >, greater < int > > Q; however, we need not only the minimum value, but also the number corresponding to the minimum value, because we need to extract G[u][i] from the edge set according to the number U. Then we use the pair provided in STL directly, but we need to make [pair (d[i], I), because the smallest d[i] is taken in comparison, and the comparison of pair is to compare first and then second

For ease of use, the algorithm is encapsulated into a structure

```typedef pair<int,int> P;
const int maxn=1e5+10;   //If you need to print out the path, 1e5 will burst the memory
const int maxm=2e5+10;

struct edge{
int from,to,w;
edge(int a,int b,int c):from(a),to(b),w(c){}
}

struct Dijkstra{
int n,m;  //Number of nodes and sides
vector<edge> edges;
vector<int> G[maxn]; //The number of all to sides under each from is recorded
bool vis[maxn]; //Determine whether to mark
int d[maxn];    //Distance from starting point to each node
//int p[maxn]; / / the shortest previous edge

void init(int n){  //Initialize structure
this->n=n;
for(int i=0;i<=n;i++) G[i].clear();
}

edges.push_back(edge(from,to,w));
m=edges.size();         //Continuously update the number of sides
G[from].push_back(m-1); //Because the number of each edge is unique in the edges array, just save the number (the number starts from 0, so M-1 is needed)
}

void dijkstra(int s){
priority_queue<P,vector<P>,greater<P> > q;
memset(vis,0,sizeof(vis));
memset(d,0x3f,sizeof(d));
d[s]=0;
q.push(make_pair(0,s)); //First construct a pair from s to itself, and it is obvious that d[s]=0
while(!q.empty()){
P pr=q.top();
q.pop();
int u=x.second;
if(vis[u]) continue;
vis[u]=1;
for(int i=0;i<G[u].size();i++){
edge &e=edges[G[u][i]];
if(d[e.to]>d[u]+e.w){
d[e.to]=d[u]+e.w;
//p[e.to]=G[u][i]; / / record the shortest path
q.push(make_pair(d[e.to],e.to)); //There are multiple sides with the same starting point and ending point, all of which need to join the team
}
}
}
}

void Print(){ //Print d[i]
for(int i=1;i<=n;i++) printf("%d ",d[i]);
}

};
```

Chain forward star

Understand Chain forward star We can easily find that the idea of implementation is exactly the same as the adjacency list. However, the chain forward star is better than the above-mentioned adjacency list in both time and space, so we will try our best to use the chain forward star when we write the adjacency list in the future

There is a little change in the following code, which is also mentioned in purple book. Instead of Using vis tag array, we can use "if(pr.first!=d[u]) continue"; ", because we are here to see whether the minimum value of D taken out of the queue is equal to d[u]. If it is equal, then we don't need to judge. Because after entering the queue, we must take out the shortest circuit, and our d[u] was updated to the shortest circuit value last time

```typedef pair<int,int> P;
const int maxn=1e5+10;
const int maxm=2e5+10;

struct node{
int to,next,w;
};

struct Dijkstra{
int n;
int tot;
node edge[maxm];
int d[maxn];

void init(int n){
this->n=n;
tot=0;
}

tot++;
edge[tot].w=w;
edge[tot].to=v;
}

void dijkstra(int s){
priority_queue<P,vector<P>,greater<P> > q;
memset(d,0x3f,sizeof(d));
d[s]=0;
q.push(make_pair(0,s));
while(!q.empty()){
P pr=q.top();
q.pop();
int u=pr.second;
if(pr.first!=d[u]) continue;
int v=edge[i].to;
int w=edge[i].w;
if(d[v]>d[u]+w){
d[v]=d[u]+w;
q.push(make_pair(d[v],v));
}
}
}
}

void Print(){
for(int i=1;i<=n;i++) printf("%d ",d[i]);
}

};
```  74 original articles published, praised 3, visited 1770

Posted by lbaxterl on Sat, 08 Feb 2020 00:33:25 -0800