洛谷P1144 最短路计数

题目描述

给出一个N个顶点M条边的无向无权图,顶点编号为1~N。问从顶点1开始,到其他每个点的最短路有几条。

输入输出格式

输入格式:

 

输入第一行包含2个正整数N,M,为图的顶点数与边数。

接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。

输出格式:

 

输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可。如果无法到达顶点i则输出0。

输入输出样例

输入样例

5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5

输出样例

1
1
1
2
4

对于20%的数据,N ≤ 100;

对于60%的数据,N ≤ 1000;

对于100%的数据,N<=1000000,M<=2000000。

这道题,乍一看是求最短路的。然而看看数据范围,如果还是单纯的一条一条求最短路的话就GG了,比如下图

所以必须想一些法子解决这道题。

咱们再想一想,求最短路的话,可以用 bfs 吧?根据 bfs 特性,走到的点一定满足从起点到该点是一条最短路,所以这一个点的最短路的条数就一定等于只用一步就走到这个结点的其他结点的最短路条数之和,就像下面这张图。

到结点1的最短路有200条,到结点2的最短路有500条,结点1和结点2都能走一步到达结点三,那么到达结点3的最短路就有2500条。

代码也很简单

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<queue>
 7 using namespace std;
 8 const int maxn = 1e6 + 5;
 9 const int mod = 1e5 + 3;
10 const int INF = 0x3f3f3f3f;
11 vector<int>v[maxn];
12 int n, m;
13 int cnt[maxn], dis[maxn];
14 void bfs()
15 {
16     for(int i = 0; i < maxn; ++i) dis[i] = INF;
17     queue<int>q;
18     q.push(1); dis[1] = 0; cnt[1] = 1;
19     while(!q.empty())
20     {
21         int now = q.front(); q.pop();
22         for(int i = 0; i < v[now].size(); ++i)
23         {
24             if(dis[v[now][i]] >= dis[now] + 1)
25             {
26                 if(dis[v[now][i]] == INF) q.push(v[now][i]);
27                 dis[v[now][i]] = dis[now] + 1;
28                 cnt[v[now][i]] += cnt[now];
29                 cnt[v[now][i]] %= mod;
30             }
31         }
32     }
33 }
34 int main()
35 {
36     scanf("%d%d", &n, &m);
37     for(int i = 1; i <= m; ++i)
38     {
39         int a, b; scanf("%d%d", &a, &b);
40         v[a].push_back(b);
41         v[b].push_back(a);
42     }
43     bfs();
44     for(int i = 1; i <= n; ++i) printf("%d
", cnt[i]);
45     return 0;
46 }
原文地址:https://www.cnblogs.com/mrclr/p/8401591.html