제출 #1342411

#제출 시각아이디문제언어결과실행 시간메모리
1342411po_rag526Evacuation plan (IZhO18_plan)C++20
100 / 100
624 ms61760 KiB
#define _USE_MATH_DEFINES
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast,unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define ll long long

int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
int dx2[] = {1, -1, 0, 0, -1, 1, -1, 1};
int dy2[] = {0, 0, 1, -1, 1, 1, -1, -1};
int knightX[] = {-2, -2, 2, 2, 1, 1, -1, -1};
int knightY[] = {-1, 1, -1, 1, -2, 2, -2, 2};

const ll INF = 2e18;
const int N = 1e6 + 10, K = 100 + 10, LOG = 20;
const ll MOD = 1e9 + 7;

struct DSU {
    vector<ll> f, siz, points;

    DSU() {}
    DSU(int n) {
        init(n + 1);
    }

    void init(int n) {
        f.resize(n);
        points.resize(n, 0);
        iota(f.begin(), f.end(), 0);
        siz.assign(n, 1);
    }

    int leader(int x) {
        if(x == f[x]){
            return f[x];
        }
        return f[x] = leader(f[x]);
    }

    bool same(int x, int y) {
        return leader(x) == leader(y);
    }

    bool merge(int x, int y) {
        x = leader(x);
        y = leader(y);
        if (x == y) {
            return false;
        }

        if (siz[x] < siz[y]) {
            swap(x , y);
        }
        points[y] -= points[x];
        siz[x] += siz[y];
        f[y] = x;
        return true;
    }
    void add(int u, ll val){
        points[leader(u)] += val;
    }
    ll get(int u){
        if(f[u] == u){
            return points[u];
        }
        return points[u] + get(f[u]);
    }
    int size(int x) {
        return siz[leader(x)];
    }
};

int main() {

    
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int t = 1;
    // cin >> t;
    while (t--) {
        int n, m;
        cin >> n >> m;
        vector<array<int, 3>> ed;
        vector<vector<pair<int, int>>> adj(n + 1);
        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});
            ed.push_back({u, v, w});
        }

        vector<ll> dis(n + 1, INF);
        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> pq;
        int k;
        cin >> k;
        for(int i = 0; i < k; i++){
            int x;
            cin >> x;
            dis[x] = 0;
            pq.push({0, x});
        }
        while(!pq.empty()){
            auto [cur, u] = pq.top();
            pq.pop();
            
            if(cur != dis[u]){
                continue;
            }
            for(auto &[v, w] : adj[u]){
                ll ndis = w + dis[u];
                if(dis[v] > ndis){
                    dis[v] = ndis;
                    pq.push({ndis, v});
                }
            }
        }

        for(auto &[u, v, w] : ed){
            w = min(dis[u], dis[v]);
        }

        sort(ed.begin(), ed.end(), [&](auto& a, auto& b){
            return a[2] > b[2];
        });
        vector<vector<int>> tree(2 * n + 1);
        vector<ll> val(2 * n + 1);
        DSU d(2 * n);
        int cur = n;
        for(auto &[u, v, w] : ed){
            u = d.leader(u), v = d.leader(v);
            if(u == v){
                continue;
            }

            int neww = ++cur;
            val[neww] = w;
            tree[neww].push_back(u);
            tree[neww].push_back(v);
            d.f[u] = neww;
            d.f[v] = neww;
            d.siz[neww] = d.siz[u] + d.siz[v];
        }
        
        int timer = 0;
        vector<vector<int>> up(LOG, vector<int>(cur + 1));
        vector<int> in(cur + 1), out(cur + 1), dep(cur + 1);
        auto dfs = [&](auto&& self, int u, int p) -> void{
            in[u] = ++timer;
            up[0][u] = p;
            for(int i = 1; i < LOG; i++){
                up[i][u] = up[i - 1][up[i - 1][u]];
            }
            for(auto &i : tree[u]){
                if(i != p){
                    dep[i] = dep[u] + 1;
                    self(self, i, u);
                }
            }
            out[u] = timer;
        };
        int r = d.leader(1);
        dfs(dfs, r, r);

        auto is_ans = [&](int u, int v){
            return in[u] <= in[v] && out[u] >= out[v];
        };

        auto lca = [&](int u, int v){
            if(is_ans(u, v)){
                return u;
            }
            if(is_ans(v, u)){
                return v;
            }

            if(dep[u] < dep[v]){
                swap(u, v);
            }

            int cur = dep[u] - dep[v];
            for(int i = 0; i < LOG; i++){
                if(cur >> i & 1){
                    u = up[i][u];
                }
            }
            if(u == v){
                return u;
            }
            for(int i = LOG - 1; i >= 0; i--){
                if(up[i][u] != up[i][v]){
                    u = up[i][u];
                    v = up[i][v];
                }
            }
            return up[0][u];
        };

        int q;
        cin >> q;
        while(q--){
            int u, v;
            cin >> u >> v;
            cout << val[lca(u, v)] << endl;
        }
    }


    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...