[Template] Single source shortest path (Dijkstra algorithm)

Go to: My own blog

topic

Luogu P4779 [Template] Single source shortest path (standard version)

answer

Chained forward star (edge ​​storage structure): The structure and search traversal method of the linked list are the same, the only difference is the insertion position. The chain forward star inserts a new element into the head of the list every time. Create a linked list for each node and store all the outgoing edges of this node.

Dijkstra algorithm: This algorithm requires that the weights of all edges are non-negative. Define d[i] as the shortest path length from the starting point to the i-th node.

Algorithm flow: Suppose the starting point is s. 1. Let d[s]=0, other d[i] are infinity 2. Find the node x with the smallest d[x] from the unmarked nodes, and then mark x 3. Enumerate all the outgoing edges x of x ->y (edge ​​weight is w), if d[y]>d[x]+w, update d[y] with d[x]+w 4. Repeat 2 and 3 until all nodes are marked.

Algorithm principle: Based on greedy thinking. The node with the smallest d[x] found each time cannot be updated by the larger d[y], so d[x] must be the shortest path from s to x.

Algorithm optimization: dynamically maintain the minimum value of d[x] to reduce the search time. Use STL priority queue (large root pile), use STL pair to store d[x] and x, convert d[x] to -d[x] and store in, and convert large root pile into small root pile.

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x7fffffff;
const int maxn=1e5+5;
const int maxm=2e5+5;
int n,m,s,c;
bool v[maxn];	//v[]表示是否标记 
int head[maxn],d[maxn];	//head[x]表示节点x的链表头 
struct edge{int to,nxt,w;}e[maxm];
inline void add(int from,int to,int w)	//加边 
{
	e[++c].to=to; e[c].w=w; e[c].nxt=head[from]; head[from]=c;
}
priority_queue<pair<int,int> > q;
inline void dijkstra()
{
	for(int i=1;i<=n;i++) d[i]=inf;
	memset(v,0,sizeof(v));	//初始化 
	d[s]=0; q.push(make_pair(0,s));
	while(q.size())
	{
		int x=q.top().second; q.pop();
		if(v[x]) continue; v[x]=1;
		for(int i=head[x];i;i=e[i].nxt)	//遍历x的所有出边 
		{
			int y=e[i].to;
			if(d[y]>d[x]+e[i].w)
			{
				d[y]=d[x]+e[i].w;
				q.push(make_pair(-d[y],y));
			}
		}
	}
}

int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1;i<=m;i++)
	{
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
	}
	dijkstra();
	for(int i=1;i<=n;i++) printf("%d ",d[i]);
	
	return 0;
}

Guess you like

Origin blog.csdn.net/zjgmartin/article/details/108415521