思路:用dijkstra算法 每次以最短的路径为出发点 找下一个点 如果路径相同 就比较救援队数目
关于dijkstra可以参考https://blog.csdn.net/xiaoguapi99/article/details/86759512
#include<iostream>
#include<cstring>
using namespace std;
int n,m,s,d;
int map[501][501],num[501],path[501],len[501],jy[501],sum[501];
bool vis[501];
//map[i][j]表示i到j的距离,nun[i]表示i点有的救援人数, path[i]表示到i点的前一个点
//len[i]表示起点到i点的最短路径长度,jy[i]表示起点到i的最多救援人数,sum[i]表示起点到i点的最短路径的条数
void Dij(int start, int end){
//minStart表示这次循环从这给点出发,找与这个点相连有边的点,并且该点到相连点的距离小于相连点以找到的边的距离
int minStart = start;
for(int t=0;t<n-1;t++){ //n个点 执行n-1次
vis[minStart] = true ;
for(int i=0;i<n;i++){
if(!vis[i] && (map[minStart][i]>0)){ //两点有边并且i点还没找到最小路径
if(len[minStart]+map[minStart][i]<len[i]){ //该点到相连点的距离小于相连点已经找到路径的距离
sum[i] = sum[minStart];
len[i] = len[minStart]+map[minStart][i] ;
jy[i] = jy[minStart] + num[i] ;
path[i] = minStart; //到达i点的前一个为minStart
} else if(len[minStart]+map[minStart][i]==len[i]){ //路径长度相同比救援人数
sum[i] += sum[minStart]; //说明到起点到i点的路径多了起点到minStart点路径的条数
if(jy[minStart]+num[i]>jy[i]){
jy[i] = jy[minStart] + num[i] ;
path[i] = minStart;
}
}
}
}
int min = 999999;
for(int j=0;j<n;j++) {//找到下一个出发点, 即未找到最短路径中,路径值最小的点
if(!vis[j] && len[j]<min){
minStart = j ;
min = len[j] ;
}
}
}
cout<<sum[end]<<" "<<jy[end]<<endl;
int i = end;
int way[501];
int root=0;
while(i!=-1){
way[root++]=i;
i = path[i] ;
}
cout<<way[root-1];
for(int i=root-2;i>=0;i--){
cout<<" "<<way[i];
}
cout<<endl;
}
int main()
{
cin>>n>>m>>s>>d;
memset(vis,false,sizeof(vis));
memset(map,0,sizeof(map));
for(int i=0;i<n;i++){
cin>>num[i];
sum[i]=1;
jy[i]=0;
path[i]=-1;
len[i]=999999;
}
len[s] = 0;
jy[s] = num[s] ;
int v1,v2,l;
for(int i=0;i<m;i++){
cin>>v1>>v2>>l;
map[v1][v2] = l;
map[v2][v1] = l;
}
Dij(s, d);
}