题目链接戳这里
dijkstra模板,源点到点i,经u有更短路,更新到i的救援队数cjy[i]=cjy[u]+jy[i],更新到点i的路径数ts[i]=ts[u]
若经u是原先到i的同等长度的路径,路径之间是平等关系,和起来: ts[i] += ts[u],同理更新一下其它值,注意同等长度遇到救援队数更多时要修改路径.
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
#define mst(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for (int i = (a); i < (b); ++i)
const int inf = 0x3f3f3f3f, maxN = 505;
int N, M, S, D;
// 城市存的救援人数 图 是否已在集合S中的标记
int jy[maxN], G[maxN][maxN], ins[maxN];
// 到i城路径条数 到i城的救援人数 前一个节点 最短距离d
int ts[maxN], cjy[maxN], pre[maxN], d[maxN];
void dijkstra(int s) {
mst(ins, 0);
mst(d, inf);
mst(cjy, 0);
mst(pre, -1);
mst(ts, 0);
cjy[s] = jy[s];
ts[s] = 1;
d[s] = 0;
while (1) {
int u = -1;
rep(i, 0, N)
if (!ins[i] && (u == -1 || d[i] < d[u]))
u = i;
if (u == -1)
break;
ins[u] = 1;
rep(i, 0, N) {
if (!ins[i] && G[u][i] < inf) {
if (d[u] + G[u][i] < d[i]) {
d[i] = d[u] + G[u][i];
pre[i] = u;
cjy[i] = cjy[u] + jy[i];
ts[i] = ts[u];
} else if (d[u] + G[u][i] == d[i]) {
ts[i] += ts[u];
if (cjy[u] + jy[i] > cjy[i]) {
cjy[i] = cjy[u] + jy[i];
pre[i] = u;
}
}
}
}
}
}
void print_path(int e) {
int rec[maxN], idx = 0;
while (e != -1) {
rec[idx++] = e;
e = pre[e];
}
rep(i, 0, idx) {
if (i) printf(" ");
printf("%d", rec[idx - 1 - i]);
}
}
int main() {
// freopen("data.in", "r", stdin);
scanf("%d%d%d%d", &N, &M, &S, &D);
rep(i, 0, N) scanf("%d", &jy[i]);
int from, to, dis;
mst(G, inf);
rep(i, 0, M) {
scanf("%d %d %d", &from, &to, &dis);
G[from][to] = G[to][from] = dis;
}
dijkstra(S);
printf("%d %d\n", ts[D], cjy[D]);
print_path(D);
return 0;
}