제출 #1309334

#제출 시각아이디문제언어결과실행 시간메모리
1309334anarch_yEvacuation plan (IZhO18_plan)C++20
100 / 100
548 ms79160 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(x) begin(x), end(x)
#define sz(x) (int)x.size()
#define pb push_back

struct LCA{
    int n; 
    vector<vector<int>> adj, up, up_min;
    vector<int> depth, A;
    
    LCA(int _n){
        n = _n;
        up.resize(n+1);
        up_min.resize(n+1);
        for(int i=0; i<=n; i++){
            up[i].resize(20, 0);
            up_min[i].resize(20, 1e9);
        }
        adj.resize(n+1);
        depth.resize(n+1);
        A.resize(n+1);
    }

    void ae(int a, int b){
        adj[a].pb(b);
        adj[b].pb(a);
    }

    void dfs(int s, int p){
        depth[s] = depth[p]+1;
        up[s][0] = p;
        up_min[s][0] = A[s];
        for(auto u: adj[s]){
            if(u == p) continue;
            dfs(u, s);
        }
    }

    void init(){
        depth[0] = 0;
        dfs(1, 0);
        for(int j=1; j<20; j++){
            for(int i=1; i<=n; i++){
                up[i][j] = up[up[i][j-1]][j-1];
                up_min[i][j] = min(up_min[i][j-1], up_min[up[i][j-1]][j-1]);
            }
        }    
    }

    int jump(int x, int d){
        for(int i=0; i<20; i++){
            if(d & (1<<i)) x = up[x][i];
        }
        return x;
    }

    int jump_min(int x, int d){
        int mn = 1e9;
        for(int i=0; i<20; i++){
            if(d & (1<<i)){
                mn = min(mn, up_min[x][i]);
                x = up[x][i];
            }
        }
        return mn;
    }
    
    int lca(int a, int b){
        if(depth[a] < depth[b]) swap(a, b);
        a = jump(a, depth[a]-depth[b]);

        if(a == b) return a; 
        
        for(int i=19; i>=0; i--){
            if(up[a][i] != up[b][i]){
                a = up[a][i];
                b = up[b][i];
            }
        }
        return up[a][0];
    }
    
	int dist(int a, int b){
		int c = lca(a, b);
		int d = depth[a]+depth[b]-2*depth[c];
		return d;
	}
};

struct DSU{
    vector<int> link, size;
 
    DSU(int n){
        link.resize(n+1, 0);
        size.resize(n+1, 1);
        for(int i=1; i<=n; i++) link[i] = i;
    }
 
    int find(int x){
        if(x != link[x]) link[x] = find(link[x]);
        return link[x];
    }
 
    bool same(int a, int b){
        return find(a) == find(b);
    }
    
    void merge(int a, int b){
        if(same(a, b)) return;
        a = find(a); b = find(b);
        if(size[a] > size[b]) swap(a, b);
        link[a] = b;
        size[b] += size[a];
    }
};

const int maxn = 100001;
vector<pair<int, int>> adj[maxn];

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

    int n, m; cin >> n >> m;
    vector<pair<int, int>> edges;
    for(int i=0; i<m; i++){
        int a, b, c; cin >> a >> b >> c;
        adj[a].pb({b, c}); adj[b].pb({a, c});
        edges.pb({a, b});
    }
    int k; cin >> k;
    vector<int> v(k+1);
    for(int i=1; i<=k; i++) cin >> v[i];
    vector<int> dist(n+1, 1e9);
    using T = pair<int, int>;
    priority_queue<T, vector<T>, greater<T>> pq;
    for(int i=1; i<=k; i++){
        dist[v[i]] = 0;
        pq.push({0, v[i]});
    }
    while(!pq.empty()){
        auto [d, a] = pq.top(); pq.pop();
        if(d > dist[a]) continue;
        for(auto [b, w]: adj[a]){
            if(dist[a] + w < dist[b]){
                dist[b] = dist[a] + w;
                pq.push({dist[b], b});
            }
        }
    }
    vector<vector<int>> edges1;
    for(auto [a, b]: edges){
        int c = min(dist[a], dist[b]);
        edges1.pb({c, a, b});
    }
    sort(all(edges1), greater<>());
    LCA L(n);
    for(int i=1; i<=n; i++){
        L.A[i] = dist[i];
    } 
    DSU D(n);
    for(auto w: edges1){
        int a = w[1], b = w[2];
        if(!D.same(a, b)){
            D.merge(a, b);
            L.ae(a, b);
        }
    }
    L.init();
    int q; cin >> q;
    while(q--){
        int a, b; cin >> a >> b;
        int c = L.lca(a, b);
        int d1 = L.depth[a] - L.depth[c];
        int d2 = L.depth[b] - L.depth[c];
        int mn1 = L.jump_min(a, d1);
        int mn2 = L.jump_min(b, d2);
        int ans = min({mn1, mn2, L.A[c]});
        cout << ans << "\n";
    }
}
#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...