44312023-03-27 23:50:38Error42Barátnők (50 pont)cpp17Accepted 50/50109ms23196 KiB
#include <climits>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

using ll = long long;

ll const INF = LLONG_MAX / 10;

template <ll M>
struct modular {
    ll val;

    // n >= 0
    modular(const ll n) {
        if (n < M)
            val = n;
        else if (n < 2 * M)
            val = n - M;
        else
            val = n % M;
    }

    [[nodiscard]] modular operator +(const modular& rhs) const {
        return val + rhs.val;
    }

    [[nodiscard]] modular operator -(const modular& rhs) const {
        return val + M - rhs.val;
    }

    [[nodiscard]] modular operator *(const modular& rhs) const {
        return val * rhs.val;
    }

    // p >= 0
    [[nodiscard]] modular pow(const ll& p) const {
        if (p == 0)
            return 1;

        if (p % 2 == 0)
            return (*this * *this).pow(p / 2);
        else
            return *this * pow(p - 1);
    }

    [[nodiscard]] modular inv() const {
        return pow(M - 2);
    }

    [[nodiscard]] modular operator /(const modular& rhs) const {
        return *this * rhs.inv();
    }

    modular& operator +=(const modular& rhs) {
        return *this = *this + rhs;
    }

    modular& operator -=(const modular& rhs) {
        return *this = *this - rhs;
    }

    modular& operator *=(const modular& rhs) {
        return *this = *this * rhs;
    }

    modular& operator /=(const modular& rhs) {
        return *this = *this / rhs;
    }

    explicit operator ll() const {
        return val;
    }
};

template <ll M>
ostream& operator<<(ostream& os, const modular<M>& modular) {
    cout << modular.val;
    return os;
}

using mod = modular<1'000'000'007>;

struct edge {
    int id, to;
    ll weight;
};

struct pqe {
    int to;
    ll dist;

    bool operator >(pqe const& rhs) const {
        return dist > rhs.dist;
    }
};

vector<vector<edge>> graph;

// dist, ways
pair<vector<ll>, vector<mod>> dijkstra(int const start) {
    vector<ll> dist(graph.size(), INF);
    vector<mod> ways(graph.size(), 0);
    priority_queue<pqe, vector<pqe>, greater<pqe>> pq;
    
    pq.push({ start, 0 });
    dist[start] = 0;
    ways[start] = 1;

    while (!pq.empty()) {
        auto const [cur, cur_dist] = pq.top();
        pq.pop();

        if (cur_dist > dist[cur])
            continue;

        for (auto const& [_, neigh, weight] : graph[cur]) {
            ll const new_dist = cur_dist + weight;

            if (new_dist == dist[neigh])
                ways[neigh] += ways[cur];

            if (new_dist < dist[neigh]) {
                dist[neigh] = new_dist;
                pq.push({ neigh, new_dist });
                ways[neigh] = ways[cur];
            }
        }
    }

    return { dist, ways };
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int n, m;
    cin >> n >> m;

    graph.resize(n);

    for (int i = 0; i < m; i++) {
        int u, v, t;
        cin >> u >> v >> t;
        u--; v--;

        graph[u].push_back({ i, v, t });
        graph[v].push_back({ i, u, t });
    }

    int a, b;
    cin >> a >> b;
    a--; b--;

    // structured binding declarations cannot be captured!
    auto const dijkstra_a = dijkstra(a);
    auto const dijkstra_b = dijkstra(b);

    auto const dist_a = dijkstra_a.first;
    auto const dist_b = dijkstra_b.first;

    auto const ways_a = dijkstra_a.second;
    auto const ways_b = dijkstra_b.second;

    ll const full_dist = dist_a[b];
    auto const in_route = [&](int const v) {
        return dist_a[v] + dist_b[v] == full_dist;
    };

    mod paths = 0;
    mod intersecting_paths = 0;

    for (int v = 0; v < n; v++) { 
        if (in_route(v) && dist_a[v] * 2 == full_dist) {
            paths += ways_a[v] * ways_b[v];
            intersecting_paths += ways_a[v] * ways_a[v] * ways_b[v] * ways_b[v];
        }
    }

    for (int u = 0; u < n; u++) {
        for (auto const& [id, v, weight] : graph[u]) {
            if (
                in_route(u)
                && in_route(v)
                && dist_a[u] + weight == dist_a[v]
                && dist_a[u] * 2 < full_dist
                && dist_a[v] * 2 > full_dist
            ) {
                paths += ways_a[u] * ways_b[v];

                intersecting_paths += ways_a[u] * ways_a[u] * ways_b[v] * ways_b[v];
            }
        }
    }
    
    mod ans = paths * paths - intersecting_paths;

    cout << ans << "\n";
}
SubtaskSumTestVerdictTimeMemory
base50/50
1Accepted0/03ms1832 KiB
2Accepted0/097ms20988 KiB
3Accepted2/23ms2500 KiB
4Accepted2/23ms2672 KiB
5Accepted2/23ms2808 KiB
6Accepted2/23ms2980 KiB
7Accepted2/24ms3276 KiB
8Accepted1/139ms16592 KiB
9Accepted2/264ms20436 KiB
10Accepted2/275ms22048 KiB
11Accepted2/272ms22088 KiB
12Accepted2/271ms21744 KiB
13Accepted2/275ms22400 KiB
14Accepted2/272ms22492 KiB
15Accepted2/271ms22488 KiB
16Accepted1/190ms22572 KiB
17Accepted1/1107ms22976 KiB
18Accepted1/141ms17744 KiB
19Accepted2/2109ms22952 KiB
20Accepted2/290ms22368 KiB
21Accepted2/2108ms22924 KiB
22Accepted2/282ms21432 KiB
23Accepted2/293ms23024 KiB
24Accepted2/271ms20640 KiB
25Accepted2/268ms18584 KiB
26Accepted2/286ms22520 KiB
27Accepted2/2103ms23196 KiB
28Accepted2/2101ms23096 KiB
29Accepted2/289ms21156 KiB