有空优先队列试一下。
#include<bits/stdc++.h>
using namespace std;
const int N=510;
const int inf=0x3f3f3f3f;
typedef long long ll;
int n,m,s,t,a[N],vis[N],num[N],dis[N],pre[N],road[N],g[N][N];
//N<1000用矩阵可以过,以后优先用矩阵。前向星在这题会超时!搭配优先队列用吧
void dfs(int v){
if(v==s) return ;
dfs(pre[v]);
printf("%d ",pre[v]);
}
void dij(int s,int t){
while(s!=t){//不能直接dis[v]==inf,因为要考虑多条路径
int minn=inf;
for(int v=0;v<n;v++){
if(!vis[v]&&g[s][v]!=inf){
if(dis[v]>dis[s]+g[s][v]){
dis[v]=dis[s]+g[s][v];
num[v]=num[s]+a[v];
road[v]=road[s];
pre[v]=s;
}
else if(dis[v]==dis[s]+g[s][v]){
if(num[v]<num[s]+a[v]){
num[v]=num[s]+a[v];
pre[v]=s;
}
road[v]=road[v]+road[s];
//+road[s],而不是1。v可以通过s过来是多了一类,但到s又有好几种方法
}
// if(minn>dis[v]){
// nex=v;minn=dis[v];
// }因为下面逐个遍历了,所以这里可以省了
}
}
//这里不是找到最短路就行了,还要考虑等于的情况,所以不能直接赋nex,同一层的并列情况会漏所以要遍历一遍n个数。按层的话可以试一下优先队列写
for(int i=0;i<n;i++){
if(!vis[i]&&minn>dis[i]){
s=i;minn=dis[i];
}
}
if(minn==inf) break;//找s的变了,剪枝得放后边了
vis[s]=1;
}
}
int main(){
int x,y,z;
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
for(int j=0;j<n;j++) g[i][j]=inf;
vis[i]=0;road[i]=0;
num[i]=a[i];
dis[i]=inf;pre[i]=-1;
}
for(int i=0;i<m;i++){
scanf("%d%d%d",&x,&y,&z);
g[x][y]=z;g[y][x]=z;
}
dis[s]=0;vis[s]=1;
road[s]=1;//
dij(s,t);
cout<<road[t]<<" "<<num[t]<<endl;
dfs(t);
printf("%d\n",t);
return 0;
}