标签:
题意:告诉你那n个点以及m条单向边。询问你从s点到e点最短路和比最短路长度大一的路一共有多少条。
思路:dijkstra变形。分别从起点和终点求一边dijkstra。用cnt数组分别记录从起点到达第i个点且长度为最短长度的路径数以及从原点到达第i个点且长度为最短长度的路径数。_cnt数组记录到第i个节点的距离为最短距离+1的路径数。注意_cnt[i]所记录的路径只包括第i个节点的pre节点为最短路而pre节点到第i个节点不是最短路的情况。这样可以防止重复计算。
具体的松弛操作:设u为未经过的节点中距离原点最近的点,那么枚举u的每一条边,如果dist[flag][u]+e.w==dist[flag][e.v]
那么到达v点且为最短路的路径数cnt[v]+=cnt[u]。如果dist[u]+e.w==dist[e.v]+1,那么到达v点且长度为最短路+1的路径数_cnt[v]+=cnt[u]。如果如果dist[u]+e.w<dist[e.v],先判断dist[flag][u]+e.w等不等于dist[e.v]+1,如果等于,那么原来的最短路路径数就变成了最短路长度加1的路径数_cnt[v]=cnt[v],如果不等于,那么最短路长度加1的路径数就为0。接着更新dist[v]并且让cnt[v]=cnt[u]。接着在dijkstra求出从终点到第i个点的最短路径数就好了,这一次dijkstra不需要再求最短路径+1的条数了。
然后最终的答案就等于cnt[e]再加上从起点到第i个点长度为最短路长度+1乘上终点到第i个点的最短路的路径数。
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <string> #include <map> #include <queue> #include <vector> using namespace std; typedef long long ll; const int INF=0x3f3f3f3f; const int MAXM=11000; const int MAXN=1100; struct Edge{ int v,w,nex; }edge[2][MAXM]; int head[2][MAXN]; bool vis[MAXN]; int dist[2][MAXN]; int tot1,tot2,n,m,s,e,u,v,w; int cnt[2][MAXN]; int _cnt[MAXN]; void addedge(int u,int v,int w) { edge[0][tot1].v=v; edge[0][tot1].w=w; edge[0][tot1].nex=head[0][u]; head[0][u]=tot1++; edge[1][tot2].v=u; edge[1][tot2].w=w; edge[1][tot2].nex=head[1][v]; head[1][v]=tot2++; } void dijkstra(int flag) { int ss=flag?e:s; memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) dist[flag][i]=INF; cnt[flag][ss]=1; dist[flag][ss]=0; while(1) { int u=-1; for(int v=1;v<=n;v++) if(!vis[v]&&(u==-1||dist[flag][v]<dist[flag][u])) u=v; if(u==-1) break; vis[u]=true; for(int i=head[flag][u];i!=-1;i=edge[flag][i].nex) { Edge e=edge[flag][i]; if(dist[flag][u]+e.w==dist[flag][e.v]) cnt[flag][e.v]+=cnt[flag][u]; if(dist[flag][u]+e.w==dist[flag][e.v]+1&&!flag) _cnt[e.v]+=cnt[flag][u]; if(dist[flag][u]+e.w<dist[flag][e.v]) { if(!flag) { if(dist[flag][u]+e.w+1==dist[flag][e.v]) _cnt[e.v]=cnt[flag][e.v]; else _cnt[e.v]=0; } dist[flag][e.v]=dist[flag][u]+e.w; cnt[flag][e.v]=cnt[flag][u]; } } } } void init() { tot1=tot2=0; memset(head,-1,sizeof(head)); memset(cnt,0,sizeof(cnt)); memset(_cnt,0,sizeof(cnt)); } int main() { //freopen("in.txt","r",stdin); int T; scanf("%d",&T); while(T--) { init(); scanf("%d%d",&n,&m); while(m--) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); } scanf("%d%d",&s,&e); dijkstra(0); dijkstra(1); int ans=cnt[0][e]; //printf("%d\n",ans); //for(int i=1;i<=n;i++) //printf("%d %d\n",_cnt[i],cnt[1][i]); for(int i=1;i<=n;i++) if(dist[0][i]+dist[1][i]==dist[0][e]) ans+=_cnt[i]*cnt[1][i]; printf("%d\n",ans); } return 0; }
标签:
原文地址:http://www.cnblogs.com/onlyAzha/p/4776886.html