洛谷P1144 最短路计数
题目描述
给出一个N个顶点M条边的无向无权图,顶点编号为1-N。问从顶点1开始,到其他每个点的最短路有几条。
输入输出格式
输入格式:
第一行包含22个正整数N,M,为图的顶点数与边数。
接下来M行,每行22个正整数x,y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。
输出格式:
共N行,每行一个非负整数,第ii行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出ans \bmod 100003后的结果即可。如果无法到达顶点i则输出0。
根据题意,列出以下转移方程:
如果dis[to[e]]==dis[u]+1(也就是走当前这条路是到这个点的另一种最短路)cnt[to[e]]+=cnt[u](cnt代表到u最短路个数)
如果dis[to[e]]<dis[u]+1(也就是找到了更短的最短路,那么之前的都清零)cnt[to[e]]=cnt[u]
最后注意取模
#include <iostream> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cstring> #include <queue> #define in(a) a=read() #define REP(i,k,n) for(int i=k;i<=n;i++) #define MAXN 4000010 using namespace std; inline int read(){ int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return x*f; } int n,m;; int total,head[MAXN],to[MAXN],nxt[MAXN]; int cnt[MAXN],dis[MAXN],vis[MAXN]; const int mod=100003; inline void adl(int a,int b){ total++; to[total]=b; nxt[total]=head[a]; head[a]=total; return ; } queue <int> Q; void SPFA(){ REP(i,1,n*2) dis[i]=2147483647; dis[1]=0; cnt[1]=1; Q.push(1); while(!Q.empty()){ int u=Q.front(); Q.pop(); vis[u]=0; for(int e=head[u];e;e=nxt[e]){ if(dis[u]+1==dis[to[e]]) cnt[to[e]]=(cnt[to[e]]+cnt[u])%mod; else if(dis[u]+1<dis[to[e]]){ dis[to[e]]=dis[u]+1; cnt[to[e]]=cnt[u]; if(!vis[to[e]]) Q.push(to[e]),vis[to[e]]=1; } } } return ; } int main(){ in(n),in(m); int a,b; REP(i,1,m) in(a),in(b),adl(a,b),adl(b,a); SPFA(); REP(i,1,n) printf("%d\n",cnt[i]); }