let menu = ["Home", "Algorithms", "CodeHub", "VNOI Statistics"];

Overview

CENTRE28 - CENTRE

solution.md

Gọi \(F1(u)\) là độ dài đường đi ngắn nhất từ 1 đến \(u\), \(G1(u)\) là số đường đi ngắn nhất từ 1 đến \(u\).

Gọi \(Fn(u)\) là độ dài đường đi ngắn nhất từ \(u\) đến N, \(Gn(u)\) là số đường đi ngắn nhất từ \(u\) đến N.

Đỉnh \(u (1<u<N)\) có thể chọn làm trung tâm kinh tế mới nếu đường đi ngắn nhất từ 1 đến N không đi qua \(u\), hoặc khi bỏ \(u\) vẫn còn ít nhất một đường đi ngắn nhất khác từ 1 đến N.

Chuyển điều kiện trên thành công thức:

\(F1(u)+Fn(u) > F1(n)\) hoặc \(G1(u)\times Gn(u) < G1(n)\)

main.cpp
Open in Github Download
#include <iostream>
#include <vector>
#include <climits>
#include <queue>
#include <tuple>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef vector<vector<pii>> dsk;
typedef priority_queue<pii, vector<pii>, greater<pii>> min_heap;

pair<vector<int>, vector<ll>> dijkstra(int s, const dsk &ke) {
    vector<int> f(ke.size(), INT_MAX);
    vector<ll> g(ke.size(), 0);
    min_heap heap;

    f[s] = 0;
    g[s] = 1;
    heap.push({f[s], s});
    while (!heap.empty()) {
        while (!heap.empty() && heap.top().first > f[heap.top().second]) {
            heap.pop();
        }
        if (heap.empty()) break;

        int u = heap.top().second;
        heap.pop();
        for (auto &p: ke[u]) {
            int c, v;
            tie(c, v) = p;

            if (f[u]+c < f[v]) {
                g[v] = g[u];
                f[v] = f[u] + c;
                heap.push({f[v], v});
            } else if (f[u]+c == f[v]) {
                g[v] += g[u];
            }
        }
    }

    return {f, g};
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    
    int n, m; cin >> n >> m;
    dsk ke(n+1);
    while (m--) {
        int u, v, c;
        cin >> u >> v >> c;
        ke[u].push_back({c, v});
        ke[v].push_back({c, u});
    }

    vector<int> f1, fn;
    vector<ll> g1, gn;
    tie(f1, g1) = dijkstra(1, ke);
    tie(fn, gn) = dijkstra(n, ke);

    vector<int> res;
    for (int i=2; i<n; i++) {
        if (f1[i]+fn[i] > f1[n] || g1[i]*gn[i] < g1[n]) res.push_back(i);
    }

    cout << res.size() << '\n';
    for (int x: res) cout << x << '\n';
    return 0;
}
Comments