题目
给出一个 N 个顶点 M 条边的无向无权图,顶点编号为 1 到 N。
问从顶点 1 开始,到其他每个点的最短路有几条。
输入格式
第一行包含 2 个正整数 N,M,为图的顶点数与边数。
接下来 M 行,每行两个正整数 x,y,表示有一条顶点 x 连向顶点 y 的边,请注意可能有自环与重边。
输出格式
输出 N 行,每行一个非负整数,第 i 行输出从顶点 1 到顶点 i 有多少条不同的最短路,由于答案有可能会很大,你只需要输出对 100003 取模后的结果即可。
如果无法到达顶点 i 则输出 0。
数据范围
1≤ N ≤ 10^5
1 ≤ M ≤ 2×105
思路
由于该图为无向无权图,因此最短路为经过点最少的路径。
样例:
5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5
根据样例,我们得到下面这张图。
dist[]数组储存走到当前点,最少经过的点数。
1、如果在bfs过程中,后面的点 i 比他的前驱 j 的点数+1还要大,则说明当前dist[i]中储存的不是当前点 i 所经过的最小点数。更新点 i ,dist[ i ] = dist[ j ] + 1; cnt[ i ] = cnt[ j ]。
2、如果在bfs过程中,后面的点 i 与他的前驱 j 的点数+1相等,则说明从点 j 到达点 i 也是最短路。更新点 i , cnt[ i ] = cnt[ j ] + cnt[ i ]。(注意取模)
3、如果在bfs过程中,后面的点 i 比他的前驱 j 的点数+1要小,则不进行任何操作。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10,M = 4e5 + 10,MOD = 100003;
int n,m;
int h[N],e[M],ne[M],idx;
int dist[N],cnt[N];// cnt中储存最短路的个数
queue<int> q;
void add(int a,int b)
{
e[idx] = b,ne[idx] = h[a],h[a] = idx ++;
}
void bfs()
{
memset(dist,0x3f,sizeof(dist));
dist[1] = 0;
cnt[1] = 1;
q.push(1);
while(q.size())
{
int t = q.front();
q.pop();
for(int i = h[t]; ~i ; i = ne[i])
{
int j = e[i];
if(dist[j] > dist[t] + 1)
{
dist[j] = dist[t] + 1;
cnt[j] = cnt[t];
q.push(j);
}
else if(dist[j] == dist[t] + 1)
{
cnt[j] = (cnt[j] + cnt[t]) % MOD;
}
}
}
}
int main()
{
memset(h,-1,sizeof(h));
cin >> n >> m;
int a,b;
while(m --)
{
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
bfs();
for(int i = 1; i <= n; i ++)
{
cout << cnt[i] << endl;
}
return 0;
}