问题描述
在生活中,我们常常会遇到两个地方之间怎么走最短的问题,在图中也有类似的问题,我们一般是采用迪杰斯特拉(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次,其递推式如下: 。矩阵含义为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;
}