最短路径问题Dijkstra算法

Description

给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。

Input Format

输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点t。

(1<n<=1000, 0<m<100000, s != t)

Output Format

一行有两个数, 最短距离及其花费。

Sample Input

3 2
1 2 5 6
2 3 4 5
1 3

Sample Output

9 11

只是想重温一下Dijkstra算法的实现,但找来找去找不到简单的题目,于是取上面的这道题凑数,只是作为参考其输入输出格式,并不是要解答这道题。

dijkstra算法是计算某一个源点到其他所有顶点的最短路径,将顶点分成两个集合:

一个是集合Visited,代表这个集合中的顶点都已经找到其到源点的最短路径;

另一个是集合Unvisited,代表这个集合中的顶点到源点的最短路径尚未确定。

刚开始时将源点纳入集合Visited中,然后开始遍历Unvisited集合中的顶点(每次确定一个顶点的最短路径):

每一次遍历,都要找出Unvisited集合里面距离源点最近的那个顶点min_index,将其纳入Visited集合中,接着就是Dijkstra算法最重要的步骤所在:

s:源点;

min_index:刚刚被纳入Visited集合中的顶点;

i:当前遍历到的Unvisited集合中的顶点。

比较路径s-->(...)-->min_index-->i 的长度,是否比原先的路径s-->(...)-->i 要短,如果更短则作相应的修改.

具体思路和过程写在注释里:

#include <iostream>
#include <cstring>
#include <stack>
using namespace std;
const int MAXNUM=99999;

int main()
{
	int n,m;//n个点,m条边 
	cin>>n>>m;
	int edge[n+1][n+1];//点i到点j的边的距离,为MAXNUM表示不可达 
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			edge[i][j]=MAXNUM;
					
	for(int i=0;i<m;i++)
	{
		int a,b,d,p;
		cin>>a>>b>>d>>p;//从点a到点b有无向边,其长度为d,费用为p 
		edge[a][b]=d;
		edge[b][a]=d;
	}
	int s,t;//s为起点,t为终点 
	cin>>s>>t;
	//dis[i]代表源点到点i的最短距离
	//prev[i]表示源点到点i的最短路径中,点i的前一个结点 ,
	//	可以借助这个数组一直溯源从而获得最短路径 
	//cost[i]代表源点到点i的费用 
	int dis[n+1],prev[n+1],cost[n+1];
	
	for(int i=1;i<=n;i++) {
		prev[i]=s;
	}
	for(int i=1;i<=n;i++){
		dis[i]=edge[s][i];//初始化所有节点的dis[]数组为其到源点的距离
	}
	bool visited[n+1];  //visited[i]=1代表该点已找到最短路径 
	memset(visited,0,sizeof(visited));
	visited[s]=1;
	for(int i=1;i<=n;i++)
	{
		int min_index; //剩余的点中,到原点的距离最短的那个点 
		int min=MAXNUM;//剩余的点到原点的最短距离 
		
		for(int j=1;j<=n;j++)//找出剩余点中离原点最近的点 
		{
			if(!visited[j]&&dis[j]<min)
			{
				min=dis[j];
				min_index=j;
			}
		}

		visited[min_index]=1;//表示这个点已经找到最短路径了 
		
		for(int j=1;j<=n;j++)
		{
			//遍历未访问过的点,如果从当前点min_index到该点v[j]的距离(即min+edge[j][min_index]) 
			//比原本的dis[j]更短,则修改dis,且记录下修改后的路径path 
			if(!visited[j]&&min+edge[j][min_index]<dis[j])
			{
				dis[j]=dis[min_index]+edge[j][min_index];
				prev[j]=min_index;
			}
		}
		
	}
	cout<<"从源点s到终点t的最短距离为"<<dis[t]<<endl;
	cout<<"路径:";
	stack<int> stk;
	stk.push(t);
	int tem=t;;
	while(1){
		tem=prev[tem];
		stk.push(tem);
		if(tem==s) break;
	}
	while(!stk.empty()){
		cout<<stk.top()<<" ";
		stk.pop();
	}
}


猜你喜欢

转载自blog.csdn.net/weixin_41519463/article/details/81175281