今日大年初二,期望武汉疫情早日控制!!
单源最短路
以PTA 7-35 城市间紧急救援 (25分)为例
题目
该题目要求给出从相应起点出发所得到的最短路,于是考虑单源最短路的Dijkstra算法。
Dijkstra算法
算法可以得到由指定起点出发到达其他结点的最短路径长度。
实现步骤:
- 初始化距离数组为INF
- 扫描邻接矩阵,加入起点,更新距离数组
- 外层有N-1层循环,每层循环找到距离最小且未被访问的结点,加入该结点,更新距离数组。
全部执行完之后,将可以得到一个长度为结点数目的数组,该数组存储了由结点到达其它结点的最短距离。另外,该题目还需要输出最短路径的条数以及路径,所以在更新距离数组时,需要将距离相同的路径条数以及经过的路径进行记录。
AC代码如下:
#include<bits/stdc++.h>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<string.h>
#define ll long long
#define INF 10000
#include<map>
#include<stack>
#include<queue>
#include<stdio.h>
#include<string.h>
using namespace std;
int E[505][505];
int path[505];
int cost[505];
int vis[505];
int num[505],num1[505];
int cnt[505];
int N;
int tmp;
void Dis(int st){
vis[st]=1;
for(int i=0;i<N;i++){
if(cost[i]>E[st][i]&&vis[i]==0){
cost[i]=E[st][i];
}
}
for(int i=0;i<N;i++){
//扫描距离数组中的最短路
int minn=INF,k=-1;
for(int i=0;i<N;i++){
if(cost[i]<minn&&vis[i]==0){
minn=cost[i];
k=i;
}
}
if(k==-1) break;
vis[k]=1;
//将k加入距离数组
for(int j=0;j<N;j++){
if(vis[j]==0&&cost[j]>cost[k]+E[k][j]){
cost[j]=cost[k]+E[k][j];
cnt[j]=cnt[k];
path[j]=k;//j的前一座城市是k
num[j]=num[k]+num1[j];
}else if(vis[j]==0&&cost[j]==cost[k]+E[k][j]){
cnt[j]=cnt[j]+cnt[k];
if(num[j]<num[k]+num1[j]){
num[j]=num[k]+num1[j];
path[j]=k;
}
}
}
}
}
int main(){
int M;
int s,e;
scanf("%d%d%d%d",&N,&M,&s,&e);
for(int i=0;i<N;i++){//初始化
for(int j=0;j<N;j++){
if(i!=j) E[i][j]=INF;
}
cost[i]=INF;
cnt[i]=1;
}
for(int i=0;i<N;i++){
scanf("%d",&num[i]);
num1[i]=num[i];
}
for(int i=0;i<M;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
E[a][b]=c;//无向图
E[b][a]=c;
}
Dis(s);
cout<<cnt[e];
cout<<" "<<num[e]+num[s]<<endl;
cout<<s;
int ans[505],kk=0;
ans[kk++]=e;
while(path[e]){
ans[kk++]=path[e];
e=path[e];
}
for(int i=kk-1;i>=0;i--){
cout<<" "<<ans[i];
}
return 0;
}
要善于利用字符串string啊
字符串可以直接比较大小,输入时只能利用cin进行。
来源:CSDN
作者:weixin_44773500
链接:https://blog.csdn.net/weixin_44773500/article/details/104089744