题意:
求最短路和次短路的路径数之和,其中最短路刚好比次短路小1
dist数组更新过程中, 如果 w 比当前最小值小则更新,如果刚好等于最小值,路径数就加1
同理,如果 w 比当前次小值小,比最小值大,则更新,如果刚好等于次小值,路径数加1
最后如果满足 次短路径长度 - 最短路径长度 == 1, 则由加法原理得最终的结果是,最小路径的数量加次小路径的数量。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 1005, M = 1e4 + 5, inf = 0x3f3f3f3f;
struct edge{
int v, w, next;
}e[M];
int n, m, head[N], len, dist[N][2], dp[N][2], u, v, w, S, F;
bool vis[N][2];//每种状态只考虑一次,0表示最小,1表示次小
struct node{
int v, d, tg;//tg表示点的状态,0:最短路径,1:次短路径
node(int v, int d, int tg):v(v), d(d), tg(tg){
}
bool operator < (const node &W)const {
return d > W.d;
}
};
void add(int u, int v, int w) {
e[len].v = v;
e[len].w = w;
e[len].next = head[u];
head[u] = len++;
}
void dijkstra() {
memset(dist, 0x3f, sizeof(dist));
memset(vis, false, sizeof(vis));
memset(dp, 0, sizeof(dp));
dp[S][0] = 1;
dist[S][0] = 0;
priority_queue<node> q;
q.push(node(S, 0, 0));
while(!q.empty()) {
node t = q.top();
q.pop();
int u = t.v;
int tg = t.tg;
if(vis[u][tg]) continue;
vis[u][tg] = true;
for(int j = head[u]; j; j = e[j].next) {
int v = e[j].v;
int w = e[j].w + t.d;
if(dist[v][0] > w) {
if(dist[v][0] != inf) {
dist[v][1] = dist[v][0];
dp[v][1] = dp[v][0];
q.push(node(v, dist[v][1], 1));
}
dist[v][0] = w;
dp[v][0] = dp[u][tg];
q.push(node(v, dist[v][0], 0));
}else if(dist[v][0] == w) {
dp[v][0] += dp[u][tg];
}else if(dist[v][1] > w) {
dist[v][1] = w;
dp[v][1] = dp[u][tg];
q.push(node(v, dist[v][1], 1));
}else if(dist[v][1] == w) {
dp[v][1] += dp[u][tg];
}
}
}
}
int main() {
int t;
scanf("%d", &t);
while(t--) {
memset(head, 0, sizeof(head));
len = 1;
scanf("%d%d", &n, &m);
while(m--) {
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
}
scanf("%d%d", &S, &F);
dijkstra();
if(dist[F][1] - dist[F][0] == 1)
printf("%d\n", dp[F][0] + dp[F][1]);
else
printf("%d\n", dp[F][0]);
}
return 0;
}