输入样例:
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
dijstra算法,晚点上思路
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1001;
int g[maxn][maxn];
int dist[maxn],vis[maxn],cnt[maxn],cf[maxn],ccf[maxn],pre[maxn];
void Dijkstra(int n,int s)
{
for(int i=0;i<maxn;i++)
{
vis[i]=0;
dist[i]=g[s][i];
if(dist[i]<INF) pre[i]=s;
else pre[i]=-1;
}
cnt[s]=1;
vis[s]=1;
for(int i=0;i<n;i++){
int min=INF,f=-1;
for(int j=0;j<n;j++){
if(vis[j]==0&&g[s][j]<min){//寻找下一个距离最短的城市
min=g[s][j];
f=j;//做好下一城市编号的标记
}
}
//cout<<f<<endl;
if(f==-1)break;//与其他未经过的城市不连通,退出循环
else vis[f]=1;//到达下一城市
for(int j=0;j<n;j++){
if(vis[j]==0&&g[s][j]>g[s][f]+g[f][j]){//到达某一城市的最短路径
g[s][j]=g[s][f]+g[f][j];//最短路径更新
pre[j]=f;//记录上一个城市编号
cnt[j]=cnt[f];//拷贝到达上一个城市时的最短路径条数
ccf[j]=ccf[f]+cf[j];//到达某城市召集的全部救援队数量
}
else if(vis[j]==0&&g[s][j]==g[s][f]+g[f][j]){//发现其他的最短路径
cnt[j]=cnt[j]+cnt[f];//更新到达当前城市时的最短路径条数
if(ccf[j]<ccf[f]+cf[j]){//最多救援队数量更新
pre[j]=f;//记录所经过的上一个城市编号
ccf[j]=ccf[f]+cf[j];//更新救援队总数
}
}
}
}
}
void printPath(int s,int x)
{
if(s==x)
{
cout<<x;
return ;
}
printPath(s,pre[x]);
cout<<" "<<x;
}
int main()
{
//freopen("紧急救援txt.txt","r",stdin);
int n,m,s,d;
cin>>n>>m>>s>>d;
for(int i=0;i<n;i++){
cin>>cf[i];//各个城市救援队数量
ccf[i]=cf[i];//存放最大救援队数量的结果,先初始化等于cf[i]
cnt[i]=1;//经过的城市
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i!=j)g[i][j]=g[j][i]=INF;//初始化(双向图
else g[i][j]=0;
}
}
for(int i=0;i<m;i++){
int S,D,Q;
cin>>S>>D>>Q;
g[S][D]=g[D][S]=Q;
}
Dijkstra(n,s);
cout<<cnt[d]<<" "<<cf[s]+ccf[d]<<endl;
printPath(s,d);
return 0;
}