PAT A1003 Emergency
思路:利用Dijkstra算法,从源点出发求出到其他所有点的最短路径数量以及点权和。
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 505;
const int INF = 1e9;
int rescue[maxn], G[maxn][maxn];
int weight[maxn], d[maxn], num[maxn];
bool visit[maxn];
int N, M, start, ed;
void Dijkstra(int s) {
fill(d, d + maxn, INF);
d[s] = 0;
weight[s] = rescue[s];
num[s] = 1;
// 注意这里只需要循环 N - 1 次
// 比如 N = 2 时,只需要 2 - 1 = 1 次就可以得到最短路径
for(int i = 0; i < N - 1; i++) {
int u = -1, MIN = INF;
for(int j = 0; j < N; j++)
if(!visit[j] && d[j] < MIN) {
u = j;
MIN = d[j];
}
if(u == -1) return;
visit[u] = true;
for(int v = 0; v < N; v++)
if(!visit[v] && G[u][v] != INF) {
if(d[u] + G[u][v] < d[v]) {
d[v] = d[u] + G[u][v];
weight[v] = weight[u] + rescue[v];
num[v] = num[u];
} else if(d[u] + G[u][v] == d[v]) {
if(weight[u] + rescue[v] > weight[v])
weight[v] = weight[u] + rescue[v];
num[v] += num[u];
}
}
}
}
int main() {
cin >> N >> M >> start >> ed;
for(int i = 0; i < N; i++)
cin >> rescue[i];
int u, v, w;
fill(G[0], G[0] + maxn * maxn, INF);
for(int i = 0; i < M; i++) {
cin >> u >> v >> w;
G[v][u] = G[u][v] = w;
}
Dijkstra(start);
cout << num[ed] << " " << weight[ed] << endl;
return 0;
}