最短路计数(BFS)
题目描述
给出一个 N N N 个顶点 M M M 条边的无向无权图,顶点编号为 1 ∼ N 1\sim N 1∼N。问从顶点 1 1 1 开始,到其他每个点的最短路有几条。
输入格式
第一行包含 2 2 2 个正整数 N , M N,M N,M,为图的顶点数与边数。
接下来 M M M 行,每行 2 2 2 个正整数 x , y x,y x,y,表示有一条连接顶点 x x x 和顶点 y y y 的边,请注意可能有自环与重边。
输出格式
共 N N N 行,每行一个非负整数,第 i i i 行输出从顶点 1 1 1 到顶点 i i i 有多少条不同的最短路,由于答案有可能会很大,你只需要输出 $ ans \bmod 100003$ 后的结果即可。如果无法到达顶点 i i i 则输出 0 0 0。
样例 #1
样例输入 #1
5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5
样例输出 #1
1
1
1
2
4
提示说明
1 1 1 到 5 5 5 的最短路有 4 4 4 条,分别为 2 2 2 条 1 → 2 → 4 → 5 1\to 2\to 4\to 5 1→2→4→5 和 2 2 2 条 1 → 3 → 4 → 5 1\to 3\to 4\to 5 1→3→4→5(由于 4 → 5 4\to 5 4→5 的边有 2 2 2 条)。
对于
20
%
20\%
20% 的数据,
1
≤
N
≤
100
1\le N \le 100
1≤N≤100;
对于
60
%
60\%
60% 的数据,
1
≤
N
≤
1
0
3
1\le N \le 10^3
1≤N≤103;
对于
100
%
100\%
100% 的数据,
1
≤
N
≤
1
0
6
1\le N\le10^6
1≤N≤106,
1
≤
M
≤
2
×
1
0
6
1\le M\le 2\times 10^6
1≤M≤2×106。
代码内容
// #include <iostream>
// #include <algorithm>
// #include <cstring>
// #include <stack>//栈
// #include <deque>//队列
// #include <queue>//堆/优先队列
// #include <map>//映射
// #include <unordered_map>//哈希表
// #include <vector>//容器,存数组的数,表数组的长度
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e6+10;
ll h[3*N],e[3*N],ne[3*N],idx; //邻接表
ll d[N]; //d[i]表示头结点到i结点的最短距离
ll ans[N]; //头结点到结点 i 的最短路的数量
ll mod=100003; //取模
void add(ll k,ll x) //使用邻接表来存储图
{
e[idx]=x;
ne[idx]=h[k];
h[k]=idx++;
}
void bfs() //宽度优先搜索
{
memset(d,-1,sizeof d); //将d数组初始化为空,-1
queue<int> q; //宽度优先搜素队列
d[1]=0; //将结点1的初始化为0
ans[1]=1; //顶点 1 本身最短路的数量为 1
q.push(1); //将结点1入队
while(q.size()) //循环终止条件为队列为空
{
ll t=q.front(); //将队列中的首元素赋值给t
q.pop(); //弹出队列元素
for(ll i=h[t];i!=-1;i=ne[i]) //遍历以t为头结点
{
ll j=e[i]; //e[i]表示存在一条边由i指向e[i],通过j来将其存储
if(d[j]==-1) //如果没有遍历过j结点
{
d[j]=d[t]+1; //j是t的下一个结点距离加一
ans[j]=ans[t];//交换
q.push(j); //将j入队
}
else if(d[j]==d[t]+1)
{
ans[j]+=ans[t];//相同累加
ans[j]%=mod;
}
}
}
}
int main()
{
ll n,m; //n表示无向图中结点的数量,m表示边的数量
//cin>>n>>m; //有一个测试点会超时
scanf("%lld%lld",&n,&m);
memset(h,-1,sizeof h); //初始化邻接表为-1,表示未存储
for(ll i=1;i<=m;i++) //构造无向图
{
ll x,y;
//cin>>x>>y; //有一个测试点会超时
scanf("%lld%lld",&x,&y);
add(x,y);//无向图
add(y,x);
}
bfs(); //宽度优先搜索
for(int i=1;i<=n;i++)
//cout<<ans[i]<<endl; //有一个测试点会超时
printf("%lld\n",ans[i]); //头结点到结点 i 的最短路的数量
return 0;
}