题意:给你一个有向带权图, 让你求出最短路条数, 如果次最短路的距离 = 最短路 + 1, 那么结果再加上次最短路的条数
板子题:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int inf = 0x3f3f3f3f;
int h[N], e[N<<2], ne[N<<2], f[N<<2], cnt;
void add(int u, int v, int w)
{
e[cnt] = v, f[cnt] = w, ne[cnt] = h[u], h[u] = cnt ++;
}
int dis[N][2], num[N][2]; // o 表示最短路 1表示次短路路
int vis[N][2];// 0表示最短路是否走过, 1表示次短路是否走过
int n, m;
void init()
{
cnt = 0;
for(int i = 1; i <= n; i ++)
{
dis[i][0] = dis[i][1] = inf;
vis[i][0] = vis[i][1] = 0;
num[i][0] = num[i][1] = 0;
h[i] = -1;
}
}
struct node
{
int u, w, id;
bool operator < (const node &t) const
{
return t.w < w;
}
};
void dijkstra(int s)
{
dis[s][0] = 0;
num[s][0] = 1;
priority_queue<node> q;
q.push({s, 0, 0});
while(!q.empty())
{
node t = q.top();
q.pop();
int w = t.w, id = t.id;
int x = t.u;
if(vis[x][id]) continue;//同求最短路时相似,已经找到的最(次)短路,无需重复更新
vis[x][id] = 1;//标记已经找到的最优解
for(int i = h[x]; ~i; i = ne[i])
{
int u = e[i];
int temp = w + f[i];
if(dis[u][0] > temp)//借助这条边,缩短to和起点的最短距离,同时更新次最短路
{
dis[u][1] = dis[u][0];//之前存在最短路,这样才可以将原最短路当作次短路
num[u][1] = num[u][0];
q.push({u, dis[u][1], 1});//新的次最短路,放进优先队列,看是否可以来更新其他次短路
dis[u][0] = temp;
num[u][0] = num[x][0];借助node.x和to之间的边得到的新的最短路
q.push({u, dis[u][0], 0});
}
else if(dis[u][0] == temp)//从node.x到to的边形成同样的最短路
{
num[u][0] += num[x][0];
}
else if(dis[u][1] > temp)//借助这条边,缩短to和起点的次最短距离
{
dis[u][1] = temp;
num[u][1] = num[x][id];
q.push({u, dis[u][1], 1}); // 新的次最短路,放进优先队列,看是否可以来更新其他次短路
}
else if(dis[u][1] == temp)
{
num[u][1] += num[x][id];//从node.x到to的边形成同样的次最短路
}
}
}
}
int main()
{
int t;
scanf("%d", &t);
while(t --)
{
scanf("%d%d", &n, &m);
init();
for(int i = 1; i <= m; i ++)
{
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
add(x, y, z);
}
int s, en;
scanf("%d%d", &s, &en);
dijkstra(s);
int sum = num[en][0];
if(dis[en][0] == dis[en][1] - 1)
{
sum += num[en][1];
}
printf("%d\n", sum);
}
return 0;
}