제출 #1327280

#제출 시각아이디문제언어결과실행 시간메모리
1327280kawhietEvacuation plan (IZhO18_plan)C++20
100 / 100
354 ms31692 KiB
#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL
#include "debug.h"
#else
#define dbg(...) 47
#endif

struct DSU {
    vector<int> p;
    // vector<set<int>> a;

    DSU(int n) {
        p.assign(n + 1, -1);
        // a.resize(n + 1);
        // for (int i = 1; i <= n; i++) {
        //     a[i].insert(i);
        // }
    }

    int root(int x) { return (p[x] == -1 ? x : (p[x] = root(p[x]))); }

    bool link(int x, int y) {
        x = root(x); y = root(y);
        if (x == y) return false;
        p[y] = x;
        // if (a[x].size() < a[y].size()) {
        //     swap(a[x], a[y]);
        // }
        // for (auto k : a[y]) {
        //     a[x].insert(k);
        // }
        // a[y].clear();
        return true;
    }
};

constexpr int N = 1e5 + 1;
constexpr int inf = 1e9;

int dist[N];
vector<array<int, 2>> g[N];

vector<int> adj[N];
int sz[N], depth[N], par[N];
int heavy[N], head[N], id[N];
 
void dfs(int u, int p) {
    sz[u] = 1;
    int mx = 0;
    for (auto v : adj[u]) {
        if (v == p) continue;
        par[v] = u;
        depth[v] = depth[u] + 1;
        dfs(v, u);
        sz[u] += sz[v];
        if (sz[v] > mx) {
            mx = sz[v];
            heavy[u] = v;
        }
    }
}
 
int cnt = 0;
void hld(int u, int h) {
    id[u] = cnt++;
    head[u] = h;
    if (heavy[u]) {
        hld(heavy[u], h);
    }
    for (auto v : adj[u]) {
        if (v == par[u] || v == heavy[u]) continue;
        hld(v, v);
    }
}

int n;
int st[4 * N];
int merge(int x, int y) {
    return min(x, y);
}
void update(int id, int tl, int tr, int i, int v) {
    if (tl == tr) {
        st[id] = v;
        return;
    }
    int x = (id << 1) + 1, y = x + 1, tm = (tl + tr) >> 1;
    if (i <= tm) {
        update(x, tl, tm, i, v);
    }
    else {
        update(y, tm + 1, tr, i, v);
    }
    st[id] = merge(st[x], st[y]);
}
int query(int id, int tl, int tr, int l, int r) {
    if (tl == l && tr == r) {
        return st[id];
    }
    int x = (id << 1) + 1, y = x + 1, tm = (tl + tr) >> 1;
    if (r <= tm) {
        return query(x, tl, tm, l, r);
    }
    if (l > tm) {
        return query(y, tm + 1, tr, l, r);
    }
    return merge(query(x, tl, tm, l, tm), query(y, tm + 1, tr, tm + 1, r));
}
 
int lca(int a, int b) {
    int res = 1e9;
    while (head[a] != head[b]) {
        if (depth[head[a]] < depth[head[b]]) swap(a, b);
        res = merge(res, query(0, 0, n - 1, id[head[a]], id[a]));
        a = par[head[a]];
    }
    if (depth[a] > depth[b]) {
        swap(a, b);
    }
    res = merge(res, query(0, 0, n - 1, id[a], id[b]));
    return res;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int m;
    cin >> n >> m;
    vector<array<int, 2>> e;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        e.push_back({u, v});
        g[u].push_back({v, w});
        g[v].push_back({u, w});
    }
    fill(dist, dist + N, inf);
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
    int k;
    cin >> k;
    for (int i = 0; i < k; i++) {
        int u;
        cin >> u;
        dist[u] = 0;
        q.emplace(0, u);
    }
    while (!q.empty()) {
        auto [s, u] = q.top();
        q.pop();
        if (dist[u] < s) continue;
        for (auto [v, w] : g[u]) {
            if (s + w < dist[v]) {
                dist[v] = s + w;
                q.emplace(s + w, v);
            }
        }
    }
    vector<array<int, 2>> x(n + 1);
    for (int i = 1; i <= n; i++) {
        x[i] = {dist[i], i};
    }
    ranges::sort(x);
    DSU dsu(n + 1);
    vector<bool> allowed(n + 1);
    for (int ptr = n; ptr >= 1; ptr--) {
        auto [d, u] = x[ptr];
        allowed[u] = 1;
        bool ok = 0;
        for (auto [v, _] : g[u]) {
            if (allowed[v] && dsu.link(u, v)) {
                adj[u].push_back(v);
                adj[v].push_back(u);
                ok = 1;
            }
        }
        if (!ok) continue;  
    }
    fill(st, st + 4 * N, 1e9);
    dfs(1, 0);
    hld(1, 1);
    for (int i = 1; i <= n; i++) {
        update(0, 0, n - 1, id[i], dist[i]);
    }
    int t;
    cin >> t;
    while (t--) {
        int l, r;
        cin >> l >> r;
        cout << lca(l, r) << '\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...