题意:给你一个图和起始两点,要求求出两点之间最短路和比最短路长一个单位的路径条数总和。
思路分析:看到长一个单位想到次短路,次短路要用到A*,但是发现估价函数好像不会写(其实是可以的,但蒟蒻不会)。于是我们采取dijkstra算法来解决这道问题,由于要求求出两条路径,于是dis数组开成dis[N][2],分别表示最短路长度和次短路长度,sum数组表示从起点到当前点的路径条数,那么我们更新时就会有以下四种情况:
1.若找到比当前最短路更短的路径时,这条路成为最短路,原来最短路成为次短路。
2.若当前长度和当前最短路长度相等时,sum累加一下。
3.若当前路长度在最短,次短之间,这条路变为次短路。
4..若当前长度和当前次短路长度相等时,sum累加一下。
之后就没有什么了,注意题目说是单向边。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 const int N=1e6+10; 7 struct Node{ 8 int next,to,dis; 9 }edge[N]; 10 int Head[N],tot; 11 void Add(int x,int y,int z){ 12 edge[++tot].to=y; 13 edge[tot].next=Head[x]; 14 edge[tot].dis=z; 15 Head[x]=tot; 16 } 17 int dis[N][2],sum[N][2]; 18 struct Edge{ 19 int num,dis,t; 20 Edge(int x,int y,int z){ 21 num=x;dis=y;t=z; 22 } 23 bool operator < (const Edge& a)const{ 24 return a.dis<dis; 25 } 26 }; 27 priority_queue<Edge>q; 28 int vis[N][2]; 29 void dijkstra(int x){ 30 memset(dis,0x3f,sizeof(dis)); 31 memset(sum,0,sizeof(sum)); 32 memset(vis,0,sizeof(vis)); 33 dis[x][1]=dis[x][0]=0; 34 sum[x][0]=1; 35 q.push(Edge(x,0,0)); 36 while(!q.empty()){ 37 Edge top=q.top();q.pop(); 38 if(vis[top.num][top.t]) continue; 39 vis[top.num][top.t]=1; 40 int u=top.num,t=top.t; 41 for(int i=Head[u];i;i=edge[i].next){ 42 int v=edge[i].to; 43 if(dis[v][0]>dis[u][t]+edge[i].dis){ 44 dis[v][1]=dis[v][0];sum[v][1]=sum[v][0]; 45 dis[v][0]=dis[u][t]+edge[i].dis; 46 sum[v][0]=sum[u][t]; 47 q.push(Edge(v,dis[v][0],0)); 48 q.push(Edge(v,dis[v][1],1)); 49 } 50 else if(dis[v][0]==dis[u][t]+edge[i].dis){ 51 sum[v][0]+=sum[u][t]; 52 } 53 else if(dis[v][1]>dis[u][t]+edge[i].dis){ 54 dis[v][1]=dis[u][t]+edge[i].dis; 55 sum[v][1]=sum[u][t]; 56 q.push(Edge(v,dis[v][1],1)); 57 } 58 else if(dis[v][1]==dis[u][t]+edge[i].dis){ 59 sum[v][1]+=sum[u][t]; 60 } 61 } 62 } 63 } 64 int main(){ 65 //freopen("a.txt","r",stdin); 66 int T; 67 scanf("%d",&T); 68 while(T--){ 69 memset(Head,0,sizeof(Head)); 70 memset(edge,0,sizeof(edge)); 71 memset(sum,0,sizeof(sum)); 72 int n,m; 73 scanf("%d%d",&n,&m); 74 for(int i=1;i<=m;++i){ 75 int x,y,z; 76 scanf("%d%d%d",&x,&y,&z); 77 Add(x,y,z); 78 } 79 int x,y; 80 scanf("%d%d",&x,&y); 81 dijkstra(x); 82 int ans=sum[y][0]; 83 if(dis[y][0]+1==dis[y][1]) ans+=sum[y][1];//次短路比最短路长1时累加 84 printf("%d\n",ans); 85 } 86 return 0; 87 }
原文:https://www.cnblogs.com/li-jia-hao/p/12953592.html