洛谷P1144最短路计数
题目描述
给出一个NNN个顶点MMM条边的无向无权图,顶点编号为1−N1-N1−N。问从顶点111开始,到其他每个点的最短路有几条。
输入格式
第一行包含222个正整数N,MN,MN,M,为图的顶点数与边数。
接下来MMM行,每行222个正整数x,yx,yx,y,表示有一条顶点xxx连向顶点yyy的边,请注意可能有自环与重边。
输出格式
共NNN行,每行一个非负整数,第iii行输出从顶点111到顶点iii有多少条不同的最短路,由于答案有可能会很大,你只需要输出ans mod 100003 ans \bmod 100003ansmod100003后的结果即可。如果无法到达顶点iii则输出000。
输入输出样例
输入 #1
5 7 1 2 1 3 2 4 3 4 2 3 4 5 4 5
输出 #1
1 1 1 2 4
跑一遍SPFA,松弛的时候顺便统计条数即可。注意要边加边模,开两倍边数组存储反向边。
#include <bits/stdc++.h> #define MOD 100003 using namespace std; int n,m; const int N=1000010,M=4000010;//两倍存双向边 int head[N],ver[M],edge[M],Next[M],d[N][2];//d[i][0]存储最短路距离 d[i][1]存储最短路径数目 int tot=0; queue<int>q; bool v[N]; void add(int x,int y,int z) { ver[++tot]=y; edge[tot]=z; Next[tot]=head[x]; head[x]=tot; } void spfa() { int i; for(i=1;i<=n;i++) { d[i][0]=0x3f3f3f3f; d[i][1]=0; } memset(v,0,sizeof(v)); d[1][0]=0; d[1][1]=1;//一定要初始化为1,自己到自己有一条长为0的最短路 v[1]=1; q.push(1); while(q.size()) { int x=q.front(); q.pop(); v[x]=0; for(i=head[x];i;i=Next[i]) { int y=ver[i],z=edge[i]; if(d[y][0]>d[x][0]+z) { d[y][0]=d[x][0]+z; d[y][1]=d[x][1];//能被更新的话直接继承过来 if(!v[y])q.push(y),v[y]=1; } else if(d[y][0]==d[x][0]+z) { d[y][1]=(d[y][1]+d[x][1])%MOD;//相等的话再原来的基础上添加由x到y经过长为z的边的最短路径数目(即d[x]) } } } } int main() { cin>>n>>m; int i; for(i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y,z);//存无向图 add(y,x,z); } spfa(); for(i=1;i<=n;i++) { if(d[i][0]!=0x3f3f3f3f)printf("%d\n",d[i][1]%MOD); else printf("0\n"); } }