Submission #1346748

#TimeUsernameProblemLanguageResultExecution timeMemory
1346748_noobEvacuation plan (IZhO18_plan)C++20
100 / 100
245 ms56788 KiB
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

const int MAXN = 100005;
const int LOG = 19;
const long long INF = 1e18;

struct Edge {
    int u, v;
    long long w;
};

int n, m, k, q;
vector<pair<int, int>> adj[MAXN];
long long d[MAXN];
vector<Edge> edges;
vector<pair<int, long long>> tree[MAXN];
int up[MAXN][LOG], depth[MAXN];
long long mn[MAXN][LOG];
int parent[MAXN];

int find(int i) {
    if (parent[i] == i) return i;
    return parent[i] = find(parent[i]);
}

bool unite(int i, int j) {
    int root_i = find(i);
    int root_j = find(j);
    if (root_i != root_j) {
        parent[root_i] = root_j;
        return true;
    }
    return false;
}

void dfs(int u, int p, int dep, long long w) {
    depth[u] = dep;
    up[u][0] = p;
    mn[u][0] = w;
    for (int i = 1; i < LOG; i++) {
        up[u][i] = up[up[u][i - 1]][i - 1];
        mn[u][i] = min(mn[u][i - 1], mn[up[u][i - 1]][i - 1]);
    }
    for (auto& edge : tree[u]) {
        int v = edge.first;
        long long weight = edge.second;
        if (v != p) dfs(v, u, dep + 1, weight);
    }
}

long long query(int u, int v) {
    if (depth[u] < depth[v]) swap(u, v);
    long long res = min(d[u], d[v]);
    for (int i = LOG - 1; i >= 0; i--) {
        if (depth[u] - (1 << i) >= depth[v]) {
            res = min(res, mn[u][i]);
            u = up[u][i];
        }
    }
    if (u == v) return res;
    for (int i = LOG - 1; i >= 0; i--) {
        if (up[u][i] != up[v][i]) {
            res = min({res, mn[u][i], mn[v][i]});
            u = up[u][i];
            v = up[v][i];
        }
    }
    res = min({res, mn[u][0], mn[v][0]});
    return res;
}

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

    if (!(cin >> n >> m)) return 0;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    fill(d, d + n + 1, INF);
    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;

    cin >> k;
    for (int i = 0; i < k; i++) {
        int g;
        cin >> g;
        d[g] = 0;
        pq.push({0, g});
    }

    while (!pq.empty()) {
        long long dist = pq.top().first;
        int u = pq.top().second;
        pq.pop();
        if (dist > d[u]) continue;
        for (auto& edge : adj[u]) {
            int v = edge.first;
            int w = edge.second;
            if (d[v] > d[u] + w) {
                d[v] = d[u] + w;
                pq.push({d[v], v});
            }
        }
    }

    for (int u = 1; u <= n; u++) {
        for (auto& edge : adj[u]) {
            int v = edge.first;
            if (u < v) {
                edges.push_back({u, v, min(d[u], d[v])});
            }
        }
    }

    sort(edges.begin(), edges.end(), [](const Edge& a, const Edge& b) {
        return a.w > b.w;
    });

    for (int i = 1; i <= n; i++) parent[i] = i;

    for (auto& e : edges) {
        if (unite(e.u, e.v)) {
            tree[e.u].push_back({e.v, e.w});
            tree[e.v].push_back({e.u, e.w});
        }
    }

    dfs(1, 1, 0, INF);

    cin >> q;
    while (q--) {
        int s, t;
        cin >> s >> t;
        cout << query(s, t) << "\n";
    }

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...