team数组保存当前经过路径招的人数,除了出发点初始全为0.
pn数组保存最短路径数,初始为0,出发点为1.
最短路松弛时,dist更小时,更新team, pn赋新值;
dist相等时, pn加上前驱点的pn值,如果team更多,更新team
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 510;
int dist[MAXN], team[MAXN], pn[MAXN];
int num[MAXN];
vector<pair<int, int> > mp[MAXN];
void dij(int n, int begin, int end) {
memset(dist, 0x3f, sizeof(dist));
dist[begin] = 0;
memset(team, 0, sizeof(team));
team[begin] = num[begin];
memset(pn, 0, sizeof(pn));
pn[begin] = 1;
bool book[MAXN];
memset(book, false, sizeof(book));
for (int k = 0; k < n; k++) {
int u = n;
for (int j = 0; j < n; j++)
if (!book[j] && dist[u] > dist[j])
u = j;
if (u == end)
return;
book[u] = true;
for (vector<pair<int, int> >::iterator it = mp[u].begin(); it != mp[u].end(); it++) {
if (book[it->first])
continue;
if (dist[it->first] > dist[u] + it->second) {
dist[it->first] = dist[u] + it->second;
team[it->first] = team[u] + num[it->first];
pn[it->first] = pn[u];
} else if (dist[it->first] == dist[u]+it->second) {
if (team[it->first] < team[u] + num[it->first])
team[it->first] = team[u] + num[it->first];
pn[it->first] += pn[u];
}
}
}
}
int main() {
int n, m, begin, end;
while (~scanf("%d%d%d%d", &n, &m, &begin, &end)) {
for (int i = 0; i < n; i++)
scanf("%d", &num[i]);
while (m--) {
int x, y, d;
scanf("%d%d%d", &x, &y, &d);
mp[x].push_back(make_pair(y, d));
mp[y].push_back(make_pair(x, d));
}
dij(n, begin, end);
printf("%d %d\n", pn[end], team[end]);
for (int i = 0; i < n; i++)
mp[i].clear();
}
return 0;
}