Comparison of konjaku -- spfa and dijkstra

Posted by bibie on Thu, 03 Mar 2022 07:18:41 +0100

Because I haven't played the shortest board for a long time, I almost forgot the two algorithms... floyd is too simple, so I remember QAQ

No, let's play the board first. You can practice with two questions:

Weakened version: [template] single source shortest path (weakened version) - Luogu

Enhanced version: [template] single source shortest path (Standard Version) - Luogu 

0. Chain forward star

First of all, the chain forward star has forgotten its shadow... Explain to yourself: a structure edge, in which there is to (where the edge goes), dis (length of edge) and next (here refers to the next outgoing edge, such as 1 - > 2, 1 - > 3, 1 - > 4, then the function of this next is to loop the outgoing edge of 1 2 / 3 / 4) the array superscript I of the head[i] array represents the superscript of the last connected edge of node i (in the above example, I is node 1, and head[i] is finally node 4). In this way, the expression in the loop is: for(int i=head[u];i;i=edge[i].next)

struct edge{
	int next,to,dis;
}e[maxn];
int head[10005],cnt=0;
void add(int from,int to,int dis){
	e[++cnt].next=head[from];
	e[cnt].to=to;
	e[cnt].dis=dis;
	head[from]=cnt;
}

1,spfa

Oral algorithm process: given that node 1 has the following paths: 1 - > 2, 1 - > 3, 1 - > 4, how to know the shortest distance between 1 and 5 / 6... And other nodes? Obviously, we can only shorten the distance with other nodes through the connected nodes. So start from the starting point and traverse all the connected nodes. If you can shorten the distance, you can update it. On this basis, if you haven't joined the team, you can join the team (for example, a competent employee will be hired by the company, but if one day he doesn't work, he will be dismissed).

#include<bits/stdc++.h>
const long long inf=2147483647;
const int maxn=10005;
const int maxm=500005;
using namespace std;
struct edge{
	int next,to,dis;
}e[maxm];
int head[10005],cnt=0;
int n,m,s,u,v,w,vis[maxm],dis[maxm];
queue<int>q;
void add(int from,int to,int dis){
	e[++cnt].next=head[from];
	e[cnt].to=to;
	e[cnt].dis=dis;
	head[from]=cnt;
}
void spfa(){
	for(int i=1;i<=n;++i)
		dis[i]=inf;
	q.push(s);
	dis[s]=0; vis[s]=1;
	while(!q.empty()){
		int u=q.front(); q.pop();
		vis[u]=0;
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].to;
			if(dis[v]>dis[u]+e[i].dis){
				dis[v]=dis[u]+e[i].dis;
				if(vis[v]==0){
					vis[v]=1;
					q.push(v);
				}
			}
		}
	}
}
int main(){
	scanf("%d%d%d",&n,&m,&s);
	for(int i=0;i<m;++i){
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
	}
	spfa();
	for(int i=1;i<=n;++i){
		if(i!=1) cout<<' ';
		if(i==s) {
			cout<<0; continue;
		}
		cout<<dis[i];
	}
	return 0;
}

2,dijkstra

The two algorithms are very similar. The special feature of dijkstra is that it first selects the nearest target point for marking, and uses it to relax in the next step, and the marked nodes will not look back, that is, each node is used only once. It feels like it saves time and has wood! This also determines that dijkstra cannot deal with negative weight edges. More importantly, this algorithm supports heap optimization (if you need to select the nearest target point, the heap can take out the top elements of the heap in O(logn) time and delete and traverse each edge). You can use priority_queue.

#include<bits/stdc++.h>
using namespace std;
const int maxn=200005, inf=0x7fffffff;
struct edge{
	int next, to, dis;
}e[maxn];
int n,m,s,u,v,w,cnt,dis[maxn],head[maxn],vis[maxn];
struct node{
	int dis, pos;
	bool operator <(const node &x) const
	{
		return x.dis<dis;//Customer oriented 
	}
};
priority_queue<node>q;
void add(int from,int to,int dis){
	e[++cnt].next=head[from];
	e[cnt].to=to;
	e[cnt].dis=dis;
	head[from]=cnt;
}
void dij(){
	dis[s]=0;
	q.push((node){
		0,s
	});
	while(!q.empty()){
		node tmp=q.top(); q.pop();
		int d=tmp.dis, p=tmp.pos;
		if(vis[p]) continue;
		vis[p]=1;
		for(int i=head[p];i;i=e[i].next){
			int v=e[i].to;
			if(dis[v]>dis[p]+e[i].dis){
				dis[v]=dis[p]+e[i].dis;
				if(!vis[v])
					q.push((node){
						dis[v],v
					});
			}
		}
	}
}
int main(){
	cin>>n>>m>>s;
	for(int i=0;i<m;++i){
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
	}
	for(int i=1;i<=n;++i)
		dis[i]=inf;
	dij();
	for(int i=1;i<=n;++i){
		if(i!=1) cout<<' ';
		if(i==s) cout<<0;
		else cout<<dis[i];
	}
	return 0;
}

Topics: Algorithm Graph Theory