最短路径问题

问题描述

在生活中,我们常常会遇到两个地方之间怎么走最短的问题,在图中也有类似的问题,我们一般是采用迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd-Warshall)算法求解。

Dijkstra算法

算法描述

迪杰斯特拉(Dijkstra)算法用于求解图中某个源点到其他所有点的最短路径。该算法是一种贪心算法,算法思想是每次在剩余未确定最短路径的点中寻找到该源点距离最短的点,每次选择完后要更新各个点到源点的最短距离。

图例

代码实现 

#include<bits/stdc++.h>
using namespace std;
const int N=55;
const int inf=1e9;
struct Graph{
	int vexnum;
	int arcs[N][N];
};
//求源点到各点的距离 
void Dijkstra(Graph &G,int s){
	int n=G.vexnum ;
	vector<int> dis(n);//存储最短路径的权重距离 
	vector<int> vis(n);//标记数组 
	vis[s]=1;//源结点为1;
	for(int i=0;i<n;i++) dis[i]=G.arcs[s][i];//距离初始化
	for(int k=1;k<n;k++){//每次都选距离最短的顶点加入 
		int m=inf,j=-1;
		for(int i=0;i<n;i++){
			if(!vis[i] && dis[i]<m){//寻找当前最小未被访问的点 
				m=dis[i];
				j=i;
			}
		}
		if(j==-1){//如果找不到,跳出不再继续 
			break;
		}
		vis[j]=1;//找到了,标记为1 
		for(int i=0;i<n;i++){//更新其他点的最小距离 
			if(!vis[i] && G.arcs[j][i]<inf){
				dis[i]=min(dis[i],dis[j]+G.arcs[j][i]);
			}
		}
	} 
	for(int i=0;i<n;i++){//输出源点到各点的距离 
		if(dis[i]<inf){
			cout<<dis[i]<<" ";
		}
		else cout<<"-1 ";
	}
	cout<<endl;
}

int main(){
	Graph G;
	int s;//源结点 
	cin>>G.vexnum >>s;
	for(int i=0;i<G.vexnum;i++){//读取图 
		for(int j=0;j<G.vexnum;j++){
			cin>>G.arcs[i][j];
			if(G.arcs[i][j]==0) G.arcs[i][j]=inf;//如果权重为0,则无法达到 
		}
	}
	Dijkstra(G,s);
	return 0;
}
//输入 
//5 0
//0 10 0 30 100
//0 0 50 0 0
//0 0 0 0 10
//0 0 20 0 60
//0 0 0 0 0
//输出 
//-1 10 50 30 60

Floyd算法

算法描述

弗洛伊德(Floyd-Warshall)算法是利用松弛操作,将距离矩阵迭代n次,其递推式如下: A^{k}[i][j]=min(A^{k-1}[i][j],A^{k-1}[i][k]+A^{k-1}[k][j])。矩阵含义为i到j的路径经过的中间点的序号不超过k的最短距离。该算法采用动态规划思想,即在加入了某个点用于中转后,其他点之间的最短距离是否发生变化,如果变化了则更新最短距离。

图例

 代码实现

#include<bits/stdc++.h>
using namespace std;
const int INF=1e9;
const int MAX_V=105;
void floyd(vector<vector<int>> &dist,int v){
	for(int k=0;k<v;k++){//加入的中间顶点 
		for(int i=0;i<v;i++){//遍历矩阵的每一个点 
			for(int j=0;j<v;j++){
				if(dist[i][k]!=INF && dist[k][j]!=INF &&dist[i][k]+dist[k][j]<dist[i][j]){
					dist[i][j]=dist[i][k]+dist[k][j];
				}
			}
		}
	}
}
int main(){
	int v;
	cout<<"Enter the number of vertices: ";
	cin>>v;
	vector<vector<int>> dist(v,vector<int>(v,INF));//定义一个二维的dis,大小是v,每一个元素都是int的向量,大小是v,初始值是INF
	cout<<"Enter the matrix"<<endl;
	for(int i=0;i<v;i++){
		for(int j=0;j<v;j++){
			cin>>dist[i][j];
			if(dist[i][j]==0 && i!= j){
				dist[i][j]=INF;
			}
		}
		dist[i][i]=0;
	} 
	floyd(dist,v);
	cout<<"The shortest distances between every pair of vertives"<<endl;
	for(int i=0;i<v;i++){
		for(int j=0;j<v;j++){
			if(dist[i][j]==INF){
				cout<<"INF";
			}
			else{
				cout<<dist[i][j]<<" ";
			}
		}
		cout<<endl;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值