我们考虑在每一次 Dijkstra 算法时,记录一下从 (1 sim i) 最短路径的条数。
具体地说,我们在每一次遍历节点时:
- 如果 (dist_v = dist_u + 1),那么 (cnt_v += cnt_u);
- 如果 (dist_v > dist_u + 1),那么 (cnt_v = cnt_u)。
注意判等于要放在判大于之前。
#include <bits/stdc++.h>
using namespace std;
const int N = 1000003, M = 4000003, mod = 100003;
int n, m;
int tot, head[N], ver[M], nxt[M];
int dist[N], cnt[N];
bool vis[N];
inline void add(int u, int v)
{
ver[++tot] = v, nxt[tot] = head[u], head[u] = tot;
}
inline void Dij()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
cnt[1] = 1;
priority_queue <pair <int, int> > q;
q.push(make_pair(0, 1));
while (!q.empty())
{
int u = q.top().second; q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (int i = head[u]; i; i = nxt[i])
{
int v = ver[i], w = 1;
if (dist[v] == dist[u] + w)
(cnt[v] += cnt[u]) %= mod;
if (dist[v] > dist[u] + w)
{
dist[v] = dist[u] + w;
cnt[v] = cnt[u];
q.push(make_pair(-dist[v], v));
}
}
}
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= m; i+=1)
{
int u, v;
cin >> u >> v;
add(u, v), add(v, u);
}
Dij();
for (int i = 1; i <= n; i+=1)
{
cout << cnt[i] % mod << endl;
}
return 0;
}