#include<bits/stdc++.h>
using namespace std;
const int N=100;//城市的个数可修改
const int INF=1e7;//初始化无穷大为10000000
int mp[100][100];//,dist[N],p[N],n,m;//n为城市的个数,m为城市间路线的条数
int dist[N],p[N],n,m;
bool flag[N];//如果flag[i]等于true,说明顶点i已经加入到集合S;否则顶点i属于集合V-S.
void Dijkstra(int u)
{
for(int i=1;i<=n;i++)
{
dist[i]=mp[u][i];//初始化源点u到其他各个顶点的最短路径长度。
flag[i]=false;
if(dist[i]==INF)
p[i]=-1;
else
p[i]=u;
}
dist[u]=0;
flag[u]=true;//初始时,集合s中只有一个元素:源点u。
for(int i=1;i<=n;i++)
{
int temp=INF,t=u;
for(int j=1;j<=n;j++)//在集合V-S中寻找距离源点u最近的顶点t。
if(!flag[j]&&dist[j]<temp)
{
t=j;
temp=dist[j];
}
if(t==u) return ;//找不到t,跳出循环。
flag[t]=true;//否则,将t加入集合。
for(int j=1;j<=n;j++)//更新集合V-S中与t邻接的顶点到源点u的距离
if(!flag[j]&&mp[t][i]<INF)//!flag[j]表示j在V-S中
if(dist[j]>(dist[t]+mp[t][i]))
{
dist[j]=dist[t]+mp[t][i];
p[j]=t;
}
}
}
int main()
{
int u,v,w,st;
cout<<"请输入城市的个数:"<<endl;
cin>>n;
cout<<"请输入城市之间的路线的个数:"<<endl;
cin>>m;
cout<<"请输入城市之间的路线及距离:"<<endl;
for(int i=1;i<=n;i++)//初始化图的邻接矩阵
for(int j=1;j<=n;j++)
mp[i][j]=INF;//初始化邻接矩阵为无穷大
while(m--)
{
cin>>u>>v>>w;
mp[u][v]=min(mp[u][v],w);//邻接矩阵储存,保留最小的距离。
}
cout<<"请输入小明所在的位置:"<<endl;
cin>>st;
Dijkstra(st);
cout<<"小明所在的位置:"<<st<<endl;
for(int i=1;i<=n;i++)
{
cout<<"小明:"<<st<<"-"<<"要去的位置:"<<i<<endl;
if(dist[i]==INF)
cout<<"sorry,无路可达"<<endl;
else
cout<<"最短距离为:"<<dist[i]<<endl;
}
return 0;
}
第一次优化处理:增添
因为在程序中使用p[ ]数组记录了最短路往上每一个结点的前驱,因此除了显示最短路径外,还可以显示最短路往上经过了哪些城市,可以增加一段程序逆向找到该最短路往上的城市序列。
#include<bits/stdc++.h>
using namespace std;
const int N=100;//城市的个数可修改
const int INF=1e7;//初始化无穷大为10000000
int mp[100][100];//,dist[N],p[N],n,m;//n为城市的个数,m为城市间路线的条数
int dist[N],p[N],n,m;
bool flag[N];//如果flag[i]等于true,说明顶点i已经加入到集合S;否则顶点i属于集合V-S.
void Dijkstra(int u)
{
for(int i=1;i<=n;i++)
{
dist[i]=mp[u][i];//初始化源点u到其他各个顶点的最短路径长度。
flag[i]=false;
if(dist[i]==INF)
p[i]=-1;
else
p[i]=u;
}
dist[u]=0;
flag[u]=true;//初始时,集合s中只有一个元素:源点u。
for(int i=1;i<=n;i++)
{
int temp=INF,t=u;
for(int j=1;j<=n;j++)//在集合V-S中寻找距离源点u最近的顶点t。
if(!flag[j]&&dist[j]<temp)
{
t=j;
temp=dist[j];
}
if(t==u) return ;//找不到t,跳出循环。
flag[t]=true;//否则,将t加入集合。
for(int j=1;j<=n;j++)//更新集合V-S中与t邻接的顶点到源点u的距离
if(!flag[j]&&mp[t][j]<INF)//!flag[j]表示j在V-S中
if(dist[j]>(dist[t]+mp[t][j]))
{
dist[j]=dist[t]+mp[t][j];
p[j]=t;
}
}
}
void findpath(int u)
{
int x;
stack<int>s;//利用C++自带的函数创建一个栈s,需要程序头部引用#include<stack>
cout<<"源点为:"<<u<<endl;
for(int i=1;i<=n;i++)
{
x=p[i];
while(x!=-1)
{
s.push(x);
x=p[x];
}
cout<<"源点到其他各顶点最短路径为:";
while(!s.empty())
{
cout<<s.top()<<"--";//依次取栈顶元素
s.pop();//出栈
}
cout<<i<<";最短距离为:"<<dist[i]<<endl;
}
}
int main()
{
int u,v,w,st;
cout<<"请输入城市的个数:"<<endl;
cin>>n;
cout<<"请输入城市之间的路线的个数:"<<endl;
cin>>m;
cout<<"请输入城市之间的路线及距离:"<<endl;
for(int i=1;i<=n;i++)//初始化图的邻接矩阵
for(int j=1;j<=n;j++)
mp[i][j]=INF;//初始化邻接矩阵为无穷大
while(m--)
{
cin>>u>>v>>w;
mp[u][v]=min(mp[u][v],w);//邻接矩阵储存,保留最小的距离。
}
cout<<"请输入小明所在的位置:"<<endl;
cin>>st;
Dijkstra(st);
cout<<"小明所在的位置:"<<st<<endl;
for(int i=1;i<=n;i++)
{
cout<<"小明:"<<st<<"-"<<"要去的位置:"<<i<<endl;
if(dist[i]==INF)
cout<<"sorry,无路可达"<<endl;
else
cout<<"最短距离为:"<<dist[i]<<endl;
}
findpath(st);
return 0;
}
第二次优化处理:使用优先队列优化Dijkstra算法
#include<bits/stdc++.h>
using namespace std;
const int N=100;//城市的个数可修改
const int INF=1e7;//初始化无穷大为10000000
int mp[100][100];//,dist[N],p[N],n,m;//n为城市的个数,m为城市间路线的条数
int dist[N],p[N],n,m;
int flag[N];//如果flag[i]等于true,说明顶点i已经加入到集合S;否则顶点i属于集合V-S
struct Node{
int u,step;//u为顶点,step为源点到顶点u的最短路径
Node(){};
Node(int a,int sp){
u=a;//参数传递,u为顶点
step=sp;//参数传递,step为源点到顶点u的最短路径
}
bool operator<(const Node &a)const{
return step>a.step;//重载<,step(源点到顶点u的最短路径)最小值优先
}
};
void Dijkstra(int st)
{
priority_queue<Node>Q;//优先队列优化
Q.push(Node(st,0));
memset(flag,0,sizeof(flag));//初始化flag数组为0
for(int i=1;i<=n;i++)
dist[i]=INF; //初始化所有距离为无穷大
dist[st]=0;
while(!Q.empty())
{
Node it=Q.top();//优先队列队头元素为最小值
Q.pop();
int t=it.u;
if(flag[t])//说明已经找到了最短距离,该结点是队列里面的重复元素
continue;
flag[t]=1;
for(int i=1;i<=n;i++)
{
if(!flag[i]&&mp[t][i]<INF)//判断与当前点有关系的点,并且自己不可找到自己
{
if(dist[i]>dist[t]+mp[t][i])//求距离当前点的每个点的最短距离,进行松弛操作
{
dist[i]=dist[t]+mp[t][i];
Q.push(Node(i,dist[i]));//把更新后的最短距离压入优先队列(注意里面的元素有重复!)
}
}
}
}
}
int main()
{
int u,v,w,st;
cout<<"请输入城市的个数:"<<endl;
cin>>n;
cout<<"请输入城市之间的路线的个数:"<<endl;
cin>>m;
cout<<"请输入城市之间的路线及距离:"<<endl;
for(int i=1;i<=n;i++)//初始化图的邻接矩阵
for(int j=1;j<=n;j++)
mp[i][j]=INF;//初始化邻接矩阵为无穷大
while(m--)
{
cin>>u>>v>>w;
mp[u][v]=min(mp[u][v],w);//邻接矩阵储存,保留最小的距离。
}
cout<<"请输入小明所在的位置:"<<endl;
cin>>st;
Dijkstra(st);
cout<<"小明所在的位置:"<<st<<endl;
for(int i=1;i<=n;i++)
{
cout<<"小明:"<<st<<"-"<<"要去的位置:"<<i<<endl;
if(dist[i]==INF)
cout<<"sorry,无路可达"<<endl;
else
cout<<"最短距离为:"<<dist[i]<<endl;
}
return 0;
}