一道题可以学会如何求次短路和怎么求最短路个数。
每个数组都变成二维的,用于分别存储最短路和次短路。
for循环变成2*n-1。因为我们每个点都枚举两次,是双份额。
先找最短路的点,再找次短路的点。每次循环找到一个。之后
if(x<最小)更新最小值,次小值,还有两者的方法数
else if(x==最小)更新最小方法数
else if(x<次小)更新次小值和次小值的方法树
else if(x==次小)更新次小方法数
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int INF=0x3f3f3f3f; const int VM=1010; const int EM=10010; struct Edge{ int to,nxt; int cap; }edge[EM<<1]; int vis[VM][2],dis[VM][2]; int head[VM],count[VM][2]; int n,m,cnt; void addedge(int cu,int cv,int cw){ edge[cnt].to=cv; edge[cnt].cap=cw; edge[cnt].nxt=head[cu]; head[cu]=cnt++; } void Dijkstra(int src,int des){ memset(vis,0,sizeof(vis)); memset(count,0,sizeof(count)); int i=0; for(i=1;i<=n;i++){ dis[i][0]=INF; dis[i][1]=INF; } dis[src][0]=0; count[src][0]=1; int j,k,tmp,flag; for(i=1;i<=2*n-1;i++){ tmp=INF; for(j=1;j<=n;j++) if(!vis[j][0] && tmp>dis[j][0]){ k=j; flag=0; tmp=dis[j][0]; }else if(!vis[j][1] && tmp>dis[j][1]){ k=j; flag=1; tmp=dis[j][1]; } if(tmp==INF)
break; vis[k][flag]=1; for(j=head[k];j!=-1;j=edge[j].nxt){ int v=edge[j].to; if(dis[v][0]>tmp+edge[j].cap){ dis[v][1]=dis[v][0]; count[v][1]=count[v][0]; dis[v][0]=tmp+edge[j].cap; count[v][0]=count[k][flag]; }else if(dis[v][0]==tmp+edge[j].cap){ count[v][0]+=count[k][flag]; }else if(dis[v][1]>tmp+edge[j].cap){ dis[v][1]=tmp+edge[j].cap; count[v][1]=count[k][flag]; }else if(dis[v][1]==tmp+edge[j].cap){ count[v][1]+=count[k][flag]; } } } if(dis[des][1]==dis[des][0]+1) count[des][0]+=count[des][1]; printf("%d\n",count[des][0]); } int main(){ int t; scanf("%d",&t); while(t--){ cnt=0; memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); int u,v,w; while(m--){ scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); } int src,des; scanf("%d%d",&src,&des); Dijkstra(src,des); } return 0; }