题解【洛谷P1144】最短路计数

题面

我们考虑在每一次 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;
}
posted @ 2020-02-29 21:44  csxsi  阅读(88)  评论(0编辑  收藏  举报