最短路计数在求最短路时经常会用到
如https://www.luogu.org/problemnew/show/P1144
上代码
1 #include<bits/stdc++.h> 2 #define read read() 3 using namespace std; 4 const int N=1e6+5,mod=1e5+3; 5 int n,m,size; 6 int head[N],dis[N],vis[N],ans[N]; 7 8 inline int read 9 { 10 int x=0;char ch=getchar(); 11 while(ch<'0'||ch>'9')ch=getchar(); 12 while(ch>='0' && ch<='9') {x=10*x+(ch-'0'); ch=getchar();} 13 return x; 14 } 15 16 struct edge{ 17 int v,next; 18 }e[N<<1]; 19 20 inline void add(int u,int v) 21 { 22 e[++size].v=v; 23 e[size].next=head[u]; 24 head[u]=size; 25 } 26 27 inline void readdata() 28 { 29 n=read; m=read; 30 int u,v; 31 for(int i=1;i<=m;i++) 32 { 33 u=read; v=read; 34 add(u,v); 35 add(v,u); 36 } 37 } 38 39 queue<int>q; 40 inline void spfa() 41 { 42 dis[1]=0; q.push(1); vis[1]=1; ans[1]=1; 43 while(!q.empty()) 44 { 45 int u=q.front(); q.pop(); vis[u]=0; 46 for(int i=head[u];i;i=e[i].next) 47 { 48 int v=e[i].v; 49 if(dis[v]>dis[u]+1) 50 { 51 dis[v]=dis[u]+1; 52 ans[v]=ans[u]; 53 if(!vis[v]) 54 { 55 q.push(v); vis[v]=1; 56 } 57 } 58 else if(dis[v]==dis[u]+1) 59 { 60 ans[v]+=ans[u]; 61 ans[v]%=mod; 62 } 63 } 64 } 65 } 66 67 inline void work() 68 { 69 memset(dis,0x3f,sizeof(dis)); 70 spfa(); 71 for(int i=1;i<=n;i++) 72 { 73 printf("%d ",ans[i]); 74 } 75 } 76 77 int main() 78 { 79 readdata(); 80 work(); 81 return 0; 82 }
核心只有四行
1 if(dis[v] > dis[u] + 1) 2 ans[v] = ans[u]; 3 else if(dis[v]==dis[u] + 1) 4 ans[v] += ans[u];
Q:这么写为什么是对的呢?
A:如果能通过松弛操作松弛,则说明u,v在同一最短路上;
如果不能但同样是最短路,就加进来;
另附一道水题