思路
利用第一次全部赋值(dis)为无穷大然后去更新路径,使得能求出完整的路径。
(path[j]=i),存的是(i->j)。
遍历路径的时候需要用从尾(->)头,从(path[d]->path[s])
然后在计算路径的多种可能时需要对如果到达某个为止是相同的距离时候相加可能性(cnt[j]+=cnt[k])
#include <bits/stdc++.h>
using namespace std;
int n,m,s,d;
int mt[510][510],val[510];
int dis[510],vis[510],cnt[510],tot[510],path[510];
int ans[510];
void dij(int src){
for(int i=0;i<510;++i){
dis[i]=1e9,vis[i]=0;cnt[i]=0;
}
dis[src]=0,vis[src]=0;
cnt[src]=1,tot[src]=val[src];
int k;
for(int i=0;i<n;++i){
int tmp=1e9;
for(int j=0;j<n;++j){
if(!vis[j]&&tmp>dis[j]){
tmp=dis[j],k=j;
}
}
if(tmp==1e9)break;
vis[k]=1;
for(int j=0;j<n;++j){
if(!vis[j]&&dis[j]>dis[k]+mt[k][j]){
dis[j]=dis[k]+mt[k][j];
tot[j]=tot[k]+val[j];
cnt[j]=cnt[k];
path[j]=k;
}else if(!vis[j]&&dis[j]==dis[k]+mt[k][j]){
if(tot[k]+val[j]>tot[j]){
tot[j]=tot[k]+val[j];
path[j]=k;
}
cnt[j]+=cnt[k];
}
}
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&d);
for(int i=0;i<n;++i)scanf("%d",&val[i]);
for(int i=0;i<=500;++i){
for(int j=0;j<=500;++j){
mt[i][j]=1e9;
}
}
for(int i=1;i<=m;++i){
int x,y,val;scanf("%d%d%d",&x,&y,&val);
mt[x][y]=mt[y][x]=min(mt[x][y],val);
}
dij(s);
printf("%d %d
",cnt[d],tot[d]);
int cur=0;
for(int i=d;i>=0;i=path[i]){//类似链式前向星的存储方法
ans[++cur]=i;
if(i==s)break;
}
for(int i=cur;i>1;--i){
printf("%d ",ans[i]);
}
printf("%d
",ans[1]);
}