对最短路的计数操作
一般来说,绝大多数单源最短路都是可计数的,以下提供堆迪杰和SPFA的基本思路和SPFA的模板(因为只写了SPFA的)。
dij的基本思路基于贪心,其流程为:
- 找到当前确定的最短路(她是当前所有点的可能最短路中最小的)
- 用她更新其他点,使更新后最短路更小(if(dis[j]>dis[i]+d[i][j])dis[j]=dis[i]+d[i][j])
- 跳到1;
于是在2的同时记录最短路是当前值时的个数;
SPFA的基本思路类似于广搜,流程如下:
- 从记录被更新后没更新其他点的队列A中选取点;
- 用她更新其他点,使更新后最短路更小,并把不在A中的记录;
- 跳到1;
同样在2的同时记录最短路是当前值时的个数;
SPFA的最短路计数模板如下
#include<cstdio> #include<cstring> using namespace std; struct ss { int next,to; }x[400001]; int first[100001],num; int dis[100001],f[100001]; int dl[1000001],h,t,vis[100001]; void build(int f,int t) { x[++num].next=first[f]; x[num].to=t; first[f]=num; } int main() { int i,j,k; int n,m; scanf("%d%d",&n,&m); for(i=1;i<=m;i++) { scanf("%d%d",&j,&k); build(j,k); build(k,j); } memset(dis,0x3f3f3f,sizeof(dis)); h=0;t=1;dl[t]=1;dis[1]=0;f[1]=1; while(h<t) { h++; vis[dl[h]]=0; j=first[dl[h]]; while(j) { if(dis[x[j].to]==dis[dl[h]]+1) { f[x[j].to]=(f[x[j].to]+f[dl[h]])%100003; } if(dis[x[j].to]>dis[dl[h]]+1) { dis[x[j].to]=dis[dl[h]]+1; f[x[j].to]=f[dl[h]]; } if(dis[x[j].to]==dis[dl[h]]+1&&vis[x[j].to]==0) { t++; dl[t]=x[j].to; vis[x[j].to]=1; } j=x[j].next; } } for(i=1;i<=n;i++) printf("%d\n",f[i]); return 0; }
Just close your eyes, you`ll be alright, no one can hurt you after you die.