最短路计数
题目描述
给出一个N个顶点M条边的无向无权图,顶点编号为1-N。问从顶点1开始,到其他每个点的最短路有几条。
输入输出格式
输入格式:
第一行包含2个正整数N,M,为图的顶点数与边数。
接下来M行,每行2个正整数x,y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。
输出格式:
共N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出ansmod100003后的结果即可。如果无法到达顶点i则输出0。
输入输出样例
说明
1到5的最短路有4条,分别为2条1-2-4-5和2条1-3-4-5(由于4-5的边有2条)。
对于20%的数据,N ≤ 100;
对于60%的数据,N ≤ 1000;
对于100%的数据,N<=1000000,M<=2000000。
分析:
本题绝对算得上是毒瘤题。从读入开始就比较麻烦(有可能有重复的)。但是事实上本题还是最短路的一个变形,只要在每次更新后统计一下即可。
CODE:
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <iostream> 5 #include <algorithm> 6 #include <queue> 7 using namespace std; 8 const int MOD=100003; 9 const int M=3000005; 10 int head[M],to[M],nxt[M],d[M],in[M],ans[M],n,m,tot; 11 int read(){ 12 char c=getchar(); 13 int ans=0; 14 while (c<'0'||c>'9') c=getchar(); 15 while (c>='0'&&c<='9') ans=(ans<<1)+(ans<<3)+(c^48),c=getchar(); 16 return ans; 17 } 18 void out(int n){ 19 if (n<10){ 20 putchar(n+'0'); 21 return; 22 } 23 out(n/10); 24 putchar(n%10+'0'); 25 return; 26 } 27 void add(int u,int v){ 28 to[++tot]=v; 29 nxt[tot]=head[u]; 30 head[u]=tot; 31 } 32 void spfa(){ 33 memset(d,127,sizeof(d)); 34 d[1]=0;in[1]=ans[1]=1; 35 queue <int> Q; 36 Q.push(1); 37 while (!Q.empty()){ 38 int top=Q.front();Q.pop();in[top]=0; 39 for (int j=head[top];j!=-1;j=nxt[j]) 40 if (d[top]+1<=d[to[j]]){ 41 if (d[to[j]]==d[top]+1) ans[to[j]]=(ans[to[j]]+ans[top])%MOD; 42 else ans[to[j]]=ans[top]; 43 d[to[j]]=d[top]+1; 44 if (!in[to[j]]) in[to[j]]=1,Q.push(to[j]); 45 } 46 } 47 return; 48 } 49 int main(){ 50 memset(head,-1,sizeof(head)); 51 scanf("%d%d",&n,&m); 52 for (int i=1;i<=m;i++){ 53 int u=read(); 54 int v=read(); 55 add(u,v); 56 add(v,u); 57 } 58 spfa(); 59 for (int i=1;i<=n;i++) out(ans[i]),putchar('\n'); 60 return 0; 61 }