输入样例:
4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2
输出样例:
2 60
0 1 3
#include<iostream>
using namespace std;
const int N=550;
const int INF=1e9+7;
int n,m,s,d;
//输入数据
int nums[N];//城市救援队的数目
int sf[550][550];//存储城市道路
//需要更新的数据
//求解数据
int cnt[550];//起始点到该节点的最短路径数目
int maxn[550];//起始点到该节点的召集的救援队最大数目
//辅助求解
int way[550];//存储最短路径,每个节点前面的节点(方便从终点递归求解)
int flag[550];//标记该城市已经被走过
int mins[550];//起始点到该节点的最短路径长度
void dijistra(){
//起点的初始化 s
// flag[s]=1; //这里不能初始化
// way[s]=s;
cnt[s]=1;
maxn[s]=nums[s];
//从起始点开始更新节点
for(int i=0;i<n;i++){//和起始点的边
mins[i]=sf[s][i];
}
while(1){
int min_dist=INF;
int mid=-1;
for(int i=0;i<n;i++){//找到距离连通图的最短路径
//刚开始从起始点开始找最短路径,
if(flag[i]==0&&mins[i]<min_dist){
min_dist=mins[i];
mid=i;
}
}
if(mid==-1)break;
flag[mid]=1;
for(int i=0;i<n;i++){//更新其余节点于连通图的最短路径
if(flag[i]==0){
if(mins[i]>mins[mid]+sf[mid][i]){
mins[i]=mins[mid]+sf[mid][i];
cnt[i]=cnt[mid];//由mid节点连通,一条路径
maxn[i]=nums[i]+maxn[mid];//人员
way[i]=mid;
}
else{
if(mins[i]==mins[mid]+sf[mid][i]){
cnt[i]+=cnt[mid];//相等就多路径了
if(maxn[i]<maxn[mid]+nums[i]){
maxn[i]=maxn[mid]+nums[i];
way[i]=mid;//选人多的一条路
}
}
}
}
}
}
}
void Print(int t){
if(t==s){
cout<<t; return ;
}
Print(way[t]);
cout<<" "<<t;
}
int main(){
cin>>n>>m>>s>>d;
for(int i=0;i<n;i++)cin>>nums[i];
//城市道路的初始化
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i!=j)sf[i][j]=INF;
}
}
//输入城市道路
for(int i=0;i<m;i++){
int x,y,c;cin>>x>>y>>c;
sf[x][y]=c;sf[y][x]=c;
}
//dijistra算法
dijistra();
cout<<cnt[d]<<" "<<maxn[d]<<endl;
Print(d);
return 0;
}