You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
3.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define x first
#define y second
const int N = 1e3 + 13;
const int M = 1e6 + 10;
int n, m, u, v, s, f;
int dist[N][2], cnt[N][2];
bool st[N][2];
//链式前向星
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c = 0) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
struct Node {
// u: 节点号
// d:目前结点v的路径长度
// k:是最短路0还是次短路1
int u, d, k;
// POJ中结构体没有构造函数直接报编译错误
Node(int u, int d, int k) {
this->u = u, this->d = d, this->k = k;
}
const bool operator<(Node x) const {
return d > x.d;
}
};
void dijkrsta() {
priority_queue<Node> q; //通过定义结构体小于号,实现小顶堆
memset(dist, 0x3f, sizeof(dist)); //清空最小距离与次小距离数组
memset(cnt, 0, sizeof(cnt)); //清空最小距离路线个数与次小距离路线个数数组
memset(st, 0, sizeof(st)); //清空是否出队过数组
cnt[s][0] = 1; //起点s0:最短路1:有一条
cnt[s][1] = 0; //次短路路线数为0
dist[s][0] = 0; //最短路从s出发到s的距离是0
dist[s][1] = 0; //次短路从s出发到s的距离是0
q.push(Node(s, 0, 0)); //入队列
while (q.size()) {
Node x = q.top();
q.pop();
int u = x.u, k = x.k, d = x.d;
if (st[u][k]) continue; //①
st[u][k] = true;
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
int dj = d + w[i]; //原长度+到节点j的边长
if (dj == dist[j][0]) //与到j的最短长度相等则更新路径数量
cnt[j][0] += cnt[u][k];
else if (dj < dist[j][0]) { //找到更小的路线,需要更新
dist[j][1] = dist[j][0]; //次短距离被最短距离覆盖
cnt[j][1] = cnt[j][0]; //次短个数被最短个数覆盖
dist[j][0] = dj; //更新最短距离
cnt[j][0] = cnt[u][k]; //更新最短个数
q.push(Node(j, dist[j][1], 1)); //②
q.push(Node(j, dist[j][0], 0));
} else if (dj == dist[j][1]) //如果等于次短
cnt[j][1] += cnt[u][k]; //更新次短的方案数,累加
else if (dj < dist[j][1]) { //如果大于最短,小于次短,两者中间
dist[j][1] = dj; //更新次短距离
cnt[j][1] = cnt[u][k]; //更新次短方案数
q.push(Node(j, dist[j][1], 1)); //次短入队列
}
}
}
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
memset(h, -1, sizeof h);
scanf("%d %d", &n, &m);
while (m--) {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
add(a, b, c);
}
//起点和终点
scanf("%d %d", &s, &f);
//计算最短路
dijkrsta();
//输出
printf("%d\n", cnt[f][0] + (dist[f][1] == dist[f][0] + 1 ? cnt[f][1] : 0));
}
return 0;
}