P1144 짧은 수가 가장 짧은 단어 문제 문제 해결 방법

링크 제목 : https://www.luogu.org/problem/P1144
사실이 질문은, 최단 변형 문제 데이터 범위 때문에 \ (N \ 르 10 ^ 6 , M \ 르 2 \ 시간 10 ^ 6 \) 그것은 직접 사용되지 익스트라 알고리즘 최적화 또는 익스트라 + SPFA 스택 알고리즘에 사용될 수있다.
나는 달성하기 위해 SPFA 알고리즘 여기에 사용(다 익스트라는 힙 최적화 당황 않습니다)
계수로서이 문제는, 상기 어레이 아래의 의미에 기초 DIST CNT 어레이를 개방 할 필요가있다 :

  • \ (DIST [U] \) 기점 : \ (1 \) 노드에 \ (U \) 의 최단 거리;
  • \ (CNT [U] \) : 기점 \ (1 \) 노드에 \ (U \) 최단 경로 길이.

그런 경우 확장 된 큐 :

  • 만약 \ (DIST [V] \의 GT는 DIST [U] + +1의 \) 다음 업데이트 \ (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 maxn = 1000010;
const long long INF = (1LL<<60);
const long long MOD = 100003LL;
vector<int> g[maxn];
queue<int> que;
int n, m, x, y;
long long dist[maxn], cnt[maxn];
bool inq[maxn];
void spfa() {
    dist[1] = 0;
    for (int i = 2; i <= n; i ++) dist[i] = -1;
    cnt[1] = 1;
    que.push(1);
    while (!que.empty()) {
        int u = que.front();
        que.pop();
        inq[u] = false;
        int sz = g[u].size();
        for (int i = 0; i < sz; i ++) {
            int v = g[u][i];
            if (dist[v] == -1 || dist[v] >= dist[u] + 1) {
                if (dist[v] == -1 || dist[v] > dist[u] + 1) {
                    dist[v] = dist[u] + 1;
                    cnt[v] = cnt[u];
                }
                else {
                    cnt[v] = (cnt[v] + cnt[u]) % MOD;
                }
                if (!inq[v]) {
                    que.push(v);
                    inq[v] = true;
                }
            }
        }
    }
}
int main() {
    scanf("%d%d", &n, &m);
    while (m --) {
        scanf("%d%d", &x, &y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    spfa();
    for (int i = 1; i <= n; i ++)
        printf("%lld\n", cnt[i]);
    return 0;
}

저자 : zifeiy

추천

출처www.cnblogs.com/codedecision/p/11794850.html