分析
常规的Dijkstra求解最短路径的题,只不过添加了“第二标尺”——点权,并要求输出不同最短路径的数目。解题方法参见我的另一个博文:最短路径之Dijkstra算法
AC代码
#include<iostream>
#include<algorithm>
using namespace std;
const int maxv = 500;
const int inf = 1000000000;
int n, G[maxv][maxv], weight[maxv], w[maxv], d[maxv], num[maxv];
bool vis[maxv];
void Dijkstra(int s) {
/*初始化*/
fill(d, d + maxv, inf);
d[s] = 0; w[s] = weight[s]; num[s] = 1; //注意w和num的初始化方式
for (int i = 0; i < n; i++) {
int u = -1, MIN = inf;
for (int j = 0; j < n; j++) {
if (vis[j] == false && d[j] < MIN) {
u = j; MIN = d[j];
}
}
if (u == -1) return;
vis[u] = true; //当心漏掉
for (int v = 0; v < n; v++) {
if (vis[v] == false && G[u][v] != inf) {
if (d[u] + G[u][v] < d[v]) {
d[v] = d[u] + G[u][v];
w[v] = weight[v] + w[u];
num[v] = num[u];
}
else if (d[u] + G[u][v] == d[v]) {
num[v] += num[u]; //与点权无关
if (weight[v] + w[u] > w[v]) w[v] = weight[v] + w[u];
}
}
}
}
}
int main() {
int m, s, v;
cin >> n >> m >> s >> v;
for (int i = 0; i < n; i++) {
scanf("%d", &weight[i]);
}
fill(G[0], G[0] + maxv * maxv, inf);
//注意初始化G为inf,G为二维数组,G[0]表示首元素地址步长为sizeof(int)
while (m--) {
int c1, c2, len;
scanf("%d%d%d", &c1, &c2, &len);
G[c1][c2] = G[c2][c1] = len; //两个顶点之间距离
}
Dijkstra(s);
cout << num[v] <<" "<< w[v];
return 0;
}