Blue Bridge Cup training shortest path algorithm (spfa)

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/saber_wtq/article/details/79437647
Problem Description
Given a n vertices, m edges directed graph (negative edge weights may be some, but to ensure that no negative loop). Please work shortest path from point 1 to the other point (vertex numbers from 1 to n).
Input format
of the first row of two integers n, m.
The next m rows, each row having three integers u, v, l, u to v represents the length l has an edge.
Output format
common row n-1, the i-th row represents the shortest point 1 to point i + 1. 
Sample input
. 3. 3
. 1 2 -1
2 -1. 3
. 3. 1 2 
Sample Output
-1
-2 
size of the data and agreed
to the data of 10%, n = 2, m = 2 .
For 30% of the data, n <= 5, m < = 10.

To 100% of the data, 1 <= n <= 20000,1 <= m <= 200000, -10000 <= l <= 10000, can ensure to reach all vertices from any other vertex.



Analysis: Because comprising negative weights (the Dijkstra NA negative weights) and negative free ring (the SPFA NA FIG ring containing negative), the typical spfa

Click Detailed SPFA

Only two ways to build a different way adjacency list

Method a: from the chain to build adjacency list, i.e., side chain

#include<iostream>
#include<queue>
#include<cstdio>
#include<list>
using namespace std;

struct edge
{
	int dest,cost;
};

list<edge> HL[20010];//由边链表 构建图的邻接表 

int visit[20010],dis[20010]; //visit[i]记录 节点i 是否已经被访问    dis[i]记录原点到节点i的权长 

void SPFA(int Start)
{
	queue<int> Q;
	Q.push(Start);
	dis[Start]=0;  //原点到自己的权值记为0 
	visit[Start]=1;
	while(!Q.empty())
	{
		int temp=Q.front();
		Q.pop();
		visit[temp]=0;
		list<edge>::iterator first=HL[temp].begin(),last=HL[temp].end();//遍历的迭代器 
		for(;first!=last;first++)			//遍历所有以temp节点为始点的边 
		{
			if(dis[(*first).dest]>dis[temp]+(*first).cost)	//SPFA模板语句,自行理解 
			{
				dis[(*first).dest]=dis[temp]+(*first).cost;
				if(!visit[temp])
				{
					Q.push((*first).dest);
					visit[(*first).dest]=1;
				}
			}			
		} 
	}
		
}

int main()
{
	int n,m,u,v,l;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		dis[i]=9999999; //原点到其他点权值初始化为一个自定义的极大值 
		visit[i]=0; 	//开始节点都未被访问 
	}
	
	for(int i=0;i<m;i++)
	{
		scanf("%d%d%d",&u,&v,&l);
		edge E;
		E.dest=v;
		E.cost=l;
		int t=u;
		HL[t].insert(HL[t].end(),E);	//尾插边,构建邻接表 
	}
	
	SPFA(1);
	for(int i=2;i<=n;i++)
 		cout<<dis[i]<<endl;
 	return 0;
} 

Act II: The number of adjacency table set up

#include<iostream>
#include<queue>
#include<cstdio>
#include<list>
#include<cstring>
using namespace std;
const int Max=200010;

int next[Max],first[Max],u[Max],v[Max],l[Max],dis[Max],visit[Max];
// first[i]存储这节点i的第一条出发边的标号 ,next[i]存储着第i条边的上一条边的标号 
void SPFA(int start)
{
	memset(visit,0,sizeof(visit));
	queue<int> Q;
	Q.push(start);
	dis[start]=0;
	visit[start]=1;
	while(!Q.empty())
	{
		int temp=Q.front();
		Q.pop();
		visit[temp]=0;
		int k=first[temp];
		while(k!=-1)
		{
			if(dis[v[k]]>dis[temp]+l[k])
			{
				dis[v[k]]=dis[temp]+l[k];
				if(!visit[v[k]])
				{
					Q.push(v[k]);
					visit[v[k]]=1;
				}
			}
			k=next[k];
		}
	}
}

int main()
{
	int n,m,i;
	cin>>n>>m;
	for(i=1;i<=n;i++)
	{
		dis[i]=999999;
		first[i]=-1;
	}
		
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%d",&u[i],&v[i],&l[i]);
		next[i]=first[u[i]];
		first[u[i]]=i;
	}
	SPFA(1);
	for(int i=2;i<=n;i++)
 		cout<<dis[i]<<endl;
 	return 0;
	
}





Guess you like

Origin blog.csdn.net/saber_wtq/article/details/79437647