2022-04-23每日刷题打卡
代码源——每日一题
最短路计数 - 题目 - Daimayuan Online Judge
题目描述
给出一个 N 个顶点 M 条边的无向无权图。
问从顶点 1 开始,到其他每个点的最短路有几条。
输入格式
第 1 行包含两个正整数 N,M。
接下来 M 行,每行两个正整数 x,y 表示存在一条由顶点 x 到顶点 y 的边。(可能存在重边和自环)
输出格式
输出 N 行,每行一个非负整数。
第 i 行输出从顶点 1 到顶点 i 的不同最短路个数。
由于数据可能很大,你只需要输出 ans mod100003 的结果。
若顶点 1 不能到达顶点 i,请输出 0。
样例输入
5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5
样例输出
1
1
1
2
4
数据范围
1≤N≤10^ 6 ,1≤M≤2×10^6。
提示
由于数据量较大,请使用较为快速的输入/输出方式。
这题本意是考dij算法,但我叛逆用的bfs。
基础的bfs,一开始把所有的边先存在vector里(类似邻接表),数组v记录到达点i的最短路个数,f记录到达点i的最短路长度,初始化为无穷大。
bfs一开始先把点1的最短路长度改为1,然后把点1入队。每次看从当前点a到其它点b的边,如果b的最短路距离大于a点的最短路距离+1,就更新b点的最短路距离,并且把之前记录的b点的最短路个数清空,改成a点的最短路数量。因为a点可以到达b点,那么b点当前的最短路数量应该是a点的最短路数量。如果b点的最短路距离等于a的最短路距离+1,那么就加上a的最短路数量(原理同上)。
每次我们把以b点为出发点的边存入队列中(如果我们以前存过b为起点的边,那就不要再存了),让他们进行下一次的bfs。
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50, MOD = 100003;
int n, m, f[N], v[N];
bool st[N];
vector<int>dist[N];
inline int read() {
int x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x;
}
inline void write(int x) {
if (x > 9) write(x / 10);
putchar(x % 10 | '0');
}
void bfs()
{
v[1] = 1;
f[1] = 0;
queue<int>que;
que.push(1);
st[1] = true;
while (!que.empty())
{
int len = que.size();
for (int i = 0; i < len; i++)
{
int t = que.front();
que.pop();
for (int j = 0; j < dist[t].size(); j++)
{
if (f[dist[t][j]] > f[t] + 1)
{
v[dist[t][j]] = v[t];
f[dist[t][j]] = f[t] + 1;
}
else if (f[dist[t][j]] == f[t] + 1)
{
v[dist[t][j]] = (v[dist[t][j]] + v[t]) % MOD;
}
if (!st[dist[t][j]])
{
que.push(dist[t][j]);
st[dist[t][j]] = true;
}
}
}
}
}
int main()
{
n=read(),m=read();
memset(f, 127, sizeof f);
for (int i = 0; i < m; i++)
{
int x, y;
x = read(), y = read();
dist[x].push_back(y);
dist[y].push_back(x);
}
bfs();
for (int i = 1; i <= n; i++)
{
write(v[i]);
putchar('\n');
}
return 0;
}