#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=505;
const int inf=99999999;
int n,m,s,d;
int num[maxn];
int sum[maxn];
int cnt[maxn];
int dis[maxn];
int used[maxn];
int pre[maxn];
int e[maxn][maxn];
void dij(int s)
{
memset(dis,0x3f,sizeof(dis));
memset(used,0,sizeof(used));
memset(pre,-1,sizeof(pre));
dis[s]=0;//到自己的距离为0
sum[s]=num[s];//总的警卫人数
cnt[s]=1;//记录最短路的条数
while(1)
{
int v=-1;
for(int u=0;u<n;u++)
{
if(!used[u]&&(v==-1||dis[u]<dis[v]))
{
v=u;
}
}
if(v==-1)break;
//cout<<"fuck"<<endl;
used[v]=1;
for(int u=0;u<n;u++)
{
if(e[u][v]!=inf&&!used[u])
{
if (dis[u] > dis[v] + e[v][u])
{
dis[u] = dis[v] + e[v][u];
pre[u] = v;
cnt[u] = cnt[v];//从起点到u的最短路数量=从起点到v的最短路数量
sum[u] = sum[v] + num[u];//警卫数量累加
}
else if (dis[u] == dis[v] + e[v][u])
{
cnt[u] += cnt[v];//有两个到达u的最短路,最短路数量累加
if (sum[u] < sum[v] + num[u])
{
sum[u] = sum[v] + num[u];
pre[u] = v;
}
}
}
}
//for(int i=0;i<n;i++)cout<<cnt[i]<<' ';cout<<endl;
}
}
int main()
{
cin>>n>>m>>s>>d;
for(int i=0;i<n;i++)
{
cin>>num[i];
}
int tem1,tem2,tem3;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i!=j)e[i][j]=inf;
else e[i][j]=0;
}
}
while(m--)
{
cin>>tem1>>tem2>>tem3;
e[tem1][tem2]=tem3;
e[tem2][tem1]=tem3;
}
dij(s);
cout<<cnt[d]<<' '<<sum[d]<<endl;
cout<<s<<' ';
vector<int>vec;
while(d!=s)
{
vec.push_back(d);
d=pre[d];
}
int now;
int fir=1;
while(!vec.empty())
{
now=vec.back();
vec.pop_back();
if(fir)fir=0;
else cout<<' ';
cout<<now;
}cout<<endl;
return 0;
}
真的恶心。。
dij求最短路 条数+打印路径+第二权值
不学图论的我要开始图论入门了。。