首先,鄙人编程小白,并不了解算法,只是分享自己的一点见解,还请大佬勿喷~~~
我们都知道,求解图最短路径,有这几种常用方法——Dijkstra、Floyd、SPFA等等我主要想说的是Dijkstra算法,这个在《数据结构》书上提的。以下是我总结的迪杰斯特拉算法的几个特点:
1.这个算法的核心是用贪心算法实现,即每次都选取最短的路径,以此求得短的路径。
2.这个算法属于单源,即一个点(单源)到其他点的最短路径。Floyd算法属于多源,能求解任意一个点(多源)到其他点的最短路径,所以要求使用Dijkstra算法得有起点。
3.这个算法不能处理负权值的边的问题。
所以,我总结的求最小路径用Dijkstra算法的模板如下:
#include<stdio.h>//头文件,不用说了
#define inf 1000000//这里是定义一个相当于无穷大的值
int dis[1001][1001];//声明一个保留距离的数组
int vis[1001]={0};//初始化一个记录访问的数组
int n,m,s,d;//声明的全局变量
//核心算法
void Dijkstra()
{
vis[s]=1;//标记开始节点被访问过
for(int i=0;i<n;i++){
//初始化最短路径的长度为无穷
int min = inf;
int f;
for(int j=0;j<n;j++){
//寻找开始节点s到下一个距离最短的未被访问的节点
if(vis[j]==0&&dis[s][j]<min){
min=dis[s][j];//更新最短距离
f=j;//标记好下一个最短距离的节点
}
}
vis[f]=1;//标记下一个节点被访问了
for(int j=0;j<n;j++){
//求解到达某一节点的最短路径
if(vis[j]==0&&dis[s][j]>dis[s][f]+dis[f][j]){
dis[s][j]=dis[s][f]+dis[f][j];//最短路径更新
}
}
}
}
//主函数
int main()
{
scanf("%d %d %d %d",&n,&m,&s,&d);//输入有n个节点,m条边,求解s节点到d节点的最短路径
//初始化各点之间的距离为无穷,自己到自己的距离为0
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i!=j){
dis[i][j] = inf;
dis[j][i] = inf;
}
}
}
//更新各点之间的距离,有边的为具体权值,无边就还是无穷
for(int i=0;i<m;i++){
int q,w,e;
scanf("%d %d %d %d",&q,&w,&e);//输入节点q到节点w之间的距离为e
dis[q][w] = e;
dis[w][q] = e;
}
Dijkstra();//求解最短距离
printf("%d ",dis[s][d]);//输出最短距离
}
最后,附上我通过PTA作业的代码,求指点
旅游规划
#include<stdio.h>
#define inf 1000000
int dis[1001][1001];
int mon[1001][1001];
int vis[1001]={0};
int n,m,s,d;
int Dijkstra()
{
vis[s]=1;
for(int i=0;i<n;i++){
int min = inf;
int f;
for(int j=0;j<n;j++){
if(vis[j]==0&&dis[s][j]<min){//寻找下一个距离最短的城市
min=dis[s][j];
f=j;//做好下一城市编号的标记
}
}
vis[f]=1;//到达下一城市
for(int j=0;j<n;j++){
if(vis[j]==0&&dis[s][j]>dis[s][f]+dis[f][j]){//到达某一城市的最短路径
dis[s][j]=dis[s][f]+dis[f][j];//最短路径更新
mon[s][j]=mon[s][f]+mon[f][j];
}
else if(vis[j]==0&&dis[s][j]==dis[s][f]+dis[f][j]){//发现其他的最短路径
if(mon[s][j]>mon[s][f]+mon[f][j]){//最便宜路径费用更新
mon[s][j]=mon[s][f]+mon[f][j];
}
}
}
}
}
int main()
{
int people;
scanf("%d %d %d %d",&n,&m,&s,&d);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i!=j){
dis[i][j] = inf;
dis[j][i] = inf;
mon[i][j] = inf;
mon[j][i] = inf;
}
}
}
for(int i=0;i<m;i++){
int q,w,e,r;
scanf("%d %d %d %d",&q,&w,&e,&r);
dis[q][w] = e;
dis[w][q] = e;
mon[q][w] = r;
mon[w][q] = r;
}
Dijkstra();
printf("%d %d",dis[s][d],mon[s][d]);
}
城市间紧急救援
#include<stdio.h>
#define inf 1000000
int dis[1001][1001];
int cnt[1001],vis[1001]={0},man[1001],final[1001],passed[1001];
int n,m,s,d;
int Dijkstra()
{
cnt[s]=1;//开始时路径条数为1
vis[s]=1;
for(int i=0;i<n;i++){
int min = inf;
int f;
for(int j=0;j<n;j++){
if(vis[j]==0&&dis[s][j]<min){//寻找下一个距离最短的城市
min=dis[s][j];
f=j;//做好下一城市编号的标记
}
}
vis[f]=1;//到达下一城市
for(int j=0;j<n;j++){
if(vis[j]==0&&dis[s][j]>dis[s][f]+dis[f][j]){//到达某一城市的最短路径
dis[s][j]=dis[s][f]+dis[f][j];//最短路径更新
passed[j]=f;//记录上一个城市编号
cnt[j]=cnt[f];//拷贝到达上一个城市时的最短路径条数
final[j]=final[f]+man[j];//到达某城市召集的全部救援队数量
}
else if(vis[j]==0&&dis[s][j]==dis[s][f]+dis[f][j]){//发现其他的最短路径
cnt[j]=cnt[j]+cnt[f];//更新到达当前城市时的最短路径条数
if(final[j]<final[f]+man[j]){//最多救援队数量更新
passed[j]=f;//记录所经过的上一个城市编号
final[j]=final[f]+man[j];//更新救援队总数
}
}
}
}
}
int main()
{
int people;
scanf("%d %d %d %d",&n,&m,&s,&d);
for(int i=0;i<n;i++){
scanf("%d",&people);
man[i] = people;
final[i] = man[i];
cnt[i]=1;
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i!=j){
dis[i][j] = inf;
dis[j][i] = inf;
}
}
}
for(int i=0;i<m;i++){
int q,w,e;
scanf("%d %d %d",&q,&w,&e);
dis[q][w] = e;
dis[w][q] = e;
}
Dijkstra();
printf("%d %d\n",cnt[d],final[d]+man[s]);
int road[1001];
int x=0,t=d;
while(passed[t]!=0){//所经历的城市的从后往前的顺序
road[x++]=passed[t];
t=passed[t];
}
printf("%d",s);
for(int i=x-1;i>=0;i--)
printf(" %d",road[i]);
printf(" %d",d);
}
PS:这篇博客讲解的更加丰富详细,有兴趣可以阅读一下https://www.cnblogs.com/hxsyl/p/3270401.html