题意:给你一个有向图,可能有重边,让你求从s到t最短路的条数,如果次短路的长度比最短路的长度多1,那么在加上次短路的条数。
分析:
这题挺硬核的,就是顺便再记录一下起点到每个节点的次短路以及最短路与次短路的方案数,真心没啥好说的,代码肯定能看懂
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; const int maxn=1e3+1; const int maxm=1e4+1; const int inf=0x3f3f3f3f; struct Node { int to,next,val; }e[maxm]; struct px { int p,x,val; px(){} px(int P,int X,int VAL){p=P,x=X,val=VAL;} friend bool operator < (const px &x,const px &y) { return x.val>y.val; } }; int head[maxn]; bool vis[maxn<<1]; int dis[maxn][2]; int num[maxn][2]; int cnt; void add(int x,int y,int z) { e[++cnt].to=y; e[cnt].next=head[x]; e[cnt].val=z; head[x]=cnt; } int spfa(int s,int f) { memset(dis,0x3f,sizeof(dis)); memset(num,0,sizeof(num)); memset(vis,0,sizeof(vis)); dis[s][0]=0,num[s][0]=1; priority_queue<px> q;q.push(px(0,s,0)); while(!q.empty()) { px now=q.top();q.pop(); if(vis[now.x<<1|now.p]) continue; vis[now.x<<1|now.p]=1; for(int i=head[now.x];i;i=e[i].next) { int v=e[i].to,val=e[i].val; int nowval=now.val+val; int nownum=num[now.x][now.p]; if(nowval<dis[v][0]) { dis[v][1]=dis[v][0],num[v][1]=num[v][0]; dis[v][0]=nowval,num[v][0]=nownum; q.push(px(1,v,dis[v][1])); q.push(px(0,v,nowval)); } else if(nowval==dis[v][0]) num[v][0]+=nownum; else if(nowval<dis[v][1]) { dis[v][1]=nowval,num[v][1]=nownum; q.push(px(1,v,nowval)); } else if(nowval==dis[v][1]) num[v][1]+=nownum; } } if(dis[f][0]==dis[f][1]-1) return num[f][0]+num[f][1]; else return num[f][0]; } int main() { int t,n,m,x,y,z; scanf("%d",&t); while(t--) { memset(head,0,sizeof(head));cnt=0; scanf("%d%d",&n,&m); while(m--) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); } scanf("%d%d",&x,&y); printf("%d ",spfa(x,y)); } return 0; }