最短路计数(洛谷 1144)
题目描述
给出一个N个顶点M条边的无向无权图,顶点编号为1~N。问从顶点1开始,到其他每个点的最短路有几条。
输入输出格式
输入格式:
输入第一行包含2个正整数N,M,为图的顶点数与边数。
接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。
输出格式:
输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可。如果无法到达顶点i则输出0。
输入输出样例
输入样例#1:
5 7 1 2 1 3 2 4 3 4 2 3 4 5 4 5
输出样例#1:
1 1 1 2 4
说明
1到5的最短路有4条,分别为2条1-2-4-5和2条1-3-4-5(由于4-5的边有2条)。
对于20%的数据,N ≤ 100;
对于60%的数据,N ≤ 1000;
对于100%的数据,N ≤ 100000,M ≤ 200000。
/* 记录最短路的条数,一开始不知道怎么做,难道要进行n++遍spfa? 后来一思考,完全可以设一个数组f来做,在进行spfa更新dis时顺便把f更新了。 更新方法: 当到达i节点这条路与原来的路长度相同时,f[i]+=f[father]; 当这条路比原来的路径短的时候,f[i]=f[father]。 */ #include<cstdio> #include<iostream> #include<cstring> #define M 100010 #define mod 100003 using namespace std; struct node { int v,pre; };node e[M*4]; int head[M],dis[M],f[M],q[M*2],vis[M],n,m; void add(int i,int x,int y) { e[i].v=y; e[i].pre=head[x]; head[x]=i; } void spfa() { int t=0,w=1; q[1]=1; vis[1]=1; dis[1]=0; f[1]=1; while(t<w) { int u=q[++t]; vis[u]=0; for(int i=head[u];i;i=e[i].pre) if(dis[u]+1<=dis[e[i].v]) { if(dis[u]+1<dis[e[i].v]) f[e[i].v]=f[u]; else f[e[i].v]+=f[u],f[e[i].v]%=mod; dis[e[i].v]=dis[u]+1; if(!vis[e[i].v]) { vis[e[i].v]=1; q[++w]=e[i].v; } } } } int main() { memset(dis,0x3f3f3f3f,sizeof(dis)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); add(i*2-1,x,y);add(i*2,y,x); } spfa(); for(int i=1;i<=n;i++) printf("%d\n",f[i]%mod); return 0; }