题目大意:
给你一张有权有向图
然后给你一个起点和一个终点,然后问你从起点到终点的相同长度的最短路有多少条
思路:
跑两边dij
我们建一个数组ans[i]代表到i点有多少条不同的最短路
设ans[st]=1 ( st代表起点 )
第二遍跑dij的时候看一下dis[y]==dis[x]+w(y代表x指向的点,w代表权值)的情况
当是这种情况的时候就说明了有最短路是到这个点的
我们就用ans[y]+=ans[x]
表示加上了这条最短路的条数
之后输出ans[ed]即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e4+5;
struct node
{
int to,dist;
bool operator<(const node& e)const
{
return dist>e.dist;
}
} edge[N*2];
int head[N],nnext[N],vis[N],dis[N];
int ans[N];
int n;
int tot;
int st[N];
int top;
void init()
{
tot=0;
memset(ans,0,sizeof(ans));
memset(head,-1,sizeof(head));
memset(nnext,0,sizeof(nnext));
return;
}
void addedge(int from,int to,int w)
{
nnext[tot]=head[from];
head[from]=tot;
edge[tot++]= {to,w};
return;
}
void solve(int st,int en)
{
priority_queue<node>q;
memset(vis,0,sizeof(vis));
dis[st]=0;
q.push({st,0});
ans[st]=1;
while(!q.empty()){
node x=q.top();
q.pop();
int u=x.to;
if(vis[u])continue;
vis[u]=1;
for(int i=head[u];i!=-1;i=nnext[i]){
int y=edge[i].to;
if(dis[y]==dis[u]+edge[i].dist){
ans[y]+=ans[u];
q.push({y,dis[y]});
}
}
}
cout<<ans[en]<<endl;
}
void dij(int st,int en)
{
top=0;
priority_queue<node>q;
memset(vis,0,sizeof(vis));
memset(dis,0x3f3f3f3f,sizeof(dis));
dis[st]=0;
q.push({st,0});
while(!q.empty()){
node x=q.top();
q.pop();
int u=x.to;
if(vis[u])continue;
vis[u]=1;
for(int i=head[u];i!=-1;i=nnext[i]){
int y=edge[i].to;
if(dis[y]>=dis[u]+edge[i].dist){
dis[y]=dis[u]+edge[i].dist;
q.push({y,dis[y]});
}
}
}
solve(st,en);
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0);
int t;
cin>>t;
while(t--)
{
init();
int m,c;
cin>>n>>m;
int a,b;
for(int i=0; i<m; i++)
{
cin>>a>>b>>c;
addedge(a,b,c);
}
int st,en;
cin>>st>>en;
dij(st,en);
}
return 0;
}