次短路:大于最短路的最小路径;
最短路:求法很多,不说了
最短路计数:计算最短路的数量,以dijstra算法解最短路来说,多开一个计数的数组num[N],当我们跟新某一个点时,dis[u]>dis[v]+e[u][v] (u点与v点有路),更新num[u]=num[v]; 如果dis[u]=dis[v]+e[u][v],那就单独更新数量:num[u]+=num[v];
次短路算法:在最短路的基础上,次短路可以由次短路+边更新,也可以由最短路+边 跟新,这里注意一点,因为次短路更新时也会对其它次短路产生影响,所以更新次短路时也需要入队,我们先尝试更新最短路,成功的话就把原来的最短路给次短路,不成功的话就单独尝试更新次短路;
次短路数量:和最短路计数差不多,优先更新最短路,最短路更新成功时,次短路的数量就是原来最短路的数量,不成功的话就单独更新次短路,方法和最短路相同,为了知道我们每次取出的点是最短路的还是次短路的,所以有必要在队列里记录一样。
https://www.acwing.com/problem/content/385/
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>PII;
const int N=1010,M = 10010;
int n,m,s,f;
int head[N],nextt[M*2],to[M*2],len[M*2],cnt;
int dis[N][2],num[N][2],vis[N][2];
void add(int u,int v,int w){
to[cnt]=v,len[cnt]=w,nextt[cnt]=head[u],head[u]=cnt++;
}
struct node{
int to,dis,kind;
bool operator <(const node a)const{
return a.dis<dis;
}
};
void dijstra(){
memset(num,0,sizeof(num));
memset(vis,0,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
dis[s][0]=0,num[s][0]=1;
priority_queue<node>q;
q.push({s,dis[s][0],0});
while(q.size()){
int u=q.top().to,ds=q.top().dis,kind=q.top().kind;q.pop();
if(vis[u][kind])continue;
vis[u][kind]=1;
for(int i=head[u];i;i=nextt[i]){
int v=to[i];
if(dis[v][0]>dis[u][kind]+len[i]){
dis[v][1]=dis[v][0];num[v][1]=num[v][0];
q.push({v,dis[v][1],1});
dis[v][0]=dis[u][kind]+len[i];
num[v][0]=num[u][kind];
q.push({v,dis[v][0],0});
}
else if(dis[v][0]==dis[u][kind]+len[i]){
num[v][0]+=num[u][kind];
}
else if(dis[v][1]>dis[u][kind]+len[i]){
dis[v][1]=dis[u][kind]+len[i];
num[v][1]=num[u][kind];
q.push({v,dis[v][1],1});
}
else if(dis[v][1]==dis[u][kind]+len[i]){
num[v][1]+=num[u][kind];
}
}
}
}
int main(){
int t; cin>>t;
while(t--){
cin>>n>>m;
cnt=1;
memset(head,0,sizeof(head));
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
if(u==v)continue;
add(u,v,w);
}
cin>>s>>f;
dijstra();
// cout<<dis[f]<<" "<<dis1[f]<<" \n";
// cout<<num[f]<<" "<<num1[f]<<" \n";
cout<<(dis[f][1]==dis[f][0]+1?num[f][1]+num[f][0]:num[f][0])<<endl;
}
return 0;
}