题目描述
给出一个N个顶点M条边的无向无权图,顶点编号为1~N。问从顶点1开始,到其他每个点的最短路有几条。
输入输出格式
输入格式:
输入第一行包含2个正整数N,M,为图的顶点数与边数。
接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。
输出格式:
输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可。如果无法到达顶点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。
十分玄学的就过了。。。
//2018年4月21日20:17:14 #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int N = 1000001; const int M = 2000001; const int mod = 100003; int n, m; int fir[N], edge_num, nxt[M], to[M], len[M]; void addEdge(int x, int y, int z){ to[++edge_num] = y; len[edge_num] = z; nxt[edge_num] = fir[x]; fir[x] = edge_num; } int dis[N], q[N], sum[N], inq[N]; void SPFA(int A){ int head=0, tail=1; for(int i=1; i<=n; i++) dis[i] = 1e9+7; dis[A] = 0; q[head] = A; inq[head] = 1; sum[A] = 1; while(head != tail){ int x = q[head++]; inq[x] = 0; if(head % mod == 0) head %= mod; for(int p=fir[x]; p; p=nxt[p]) if(dis[to[p]] >= dis[x] + len[p]){ if(dis[to[p]] > dis[x] + len[p]) sum[to[p]] = sum[x]; else if(dis[to[p]] == dis[x] + len[p]){ sum[to[p]] = (sum[to[p]] + sum[x]) % mod; } dis[to[p]] = dis[x] + len[p]; if(!inq[to[p]]){ inq[to[p]] = 1; q[tail++] = to[p]; if(tail % mod == 0) tail %= mod; } } } } int main(){ scanf("%d%d", &n, &m); for(int i=1; i<=m; i++){ int x, y; scanf("%d%d", &x, &y); addEdge(x, y, 1); addEdge(y, x, 1); } SPFA(1); for(int i=1; i<=n; i++) printf("%d ", sum[i]); return 0; }