P1144 最短路计数 题解

发布时间 2023-10-02 09:16:55作者: yhx0322

Problem

考察算法:拓扑排序 + \(DP\) + \(Dijkstra\)

题目简述

给出一个无向无权图,问从顶点 \(1\) 开始,到其他每个点的最短路有几条。

思路

  • 先求出 \(1\) 号点到每个点的最短路 \(d_i\)

  • 分析每条边 $(x,y) $:

    如果 d[x] + 1 == d[y]:这条边有用。

  • 将所有有用的边拓扑排序。

  • 处理队列里面的每一个点 \(x\)\(dp_[i] = 1\) ,枚举 \(x\) 所有的出边 \(u\)\(dp_u += dp_x\)

  • 记住要边加边取余数!

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 2e6 + 10, MOD = 100003;
typedef pair<int, int> PII;
struct node {
    int from, to, next;
} a[N * 2];
int pre[N], k, in[N], flag[N];
queue<int> q;

int n, m, x, y, d[N], dp[N];
bool f[N];

void add(int x, int y) {
    a[++k] = (node) {x, y, pre[x]};
    pre[x] = k;
}

void Dijkstra() {
    priority_queue<PII, vector<PII>, greater<PII> > q;
    memset(d, 0x3f, sizeof(d));
    d[1] = 0;
    q.push(make_pair(0, 1));
    while (!q.empty()) {
        PII h = q.top();
        q.pop();
        int dis = h.first, p = h.second;
        if (f[p]) continue;
        f[p] = true;
        for (int i = pre[p]; i; i = a[i].next) {
            int to = a[i].to;
            if (d[p] + 1 < d[to]) {
                d[to] = d[p] + 1;
                q.push(make_pair(d[to], to));
            }
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++) {
        scanf("%d%d", &x, &y);
        add(x, y);
        add(y, x);
    }
    Dijkstra();
    for (int i = 1; i <= k; i++) {
        if (d[a[i].to] - d[a[i].from] == 1) {
            flag[i] = 1;
            in[a[i].to]++;
        }
    }
    for (int i = 1; i <= n; i++) {
        if (!in[i]) {
            if (d[i] != 0x3f3f3f3f)
                dp[i] = 1;
            q.push(i);
        }
    }
    while (!q.empty()) {
        int h = q.front();
        q.pop();
        for (int i = pre[h]; i; i = a[i].next) {
            if (!flag[i]) continue;
            int to = a[i].to;
            dp[to] = (dp[h] + dp[to]) % MOD;
            in[to]--;
            if (!in[to]) q.push(to);
        }
    }
    for (int i = 1; i <= n; i++) {
        printf("%d\n", dp[i]);
    }
    return 0;
}