제출 #1335502

#제출 시각아이디문제언어결과실행 시간메모리
1335502nguyenkhangninh99자매 도시 (APIO20_swap)C++20
100 / 100
201 ms53876 KiB
#include "swap.h"
#include<bits/stdc++.h>
using namespace std;

const int maxn = 3e5 + 5;
int up[maxn][19], deg[maxn], ok[maxn], h[maxn];
int res[maxn], val[maxn], p[maxn], n;
vector<int> adj[maxn];

int find(int u){
    return (p[u] == u ? u : p[u] = find(p[u]));
}
void merge(int w, int u, int v){
    bool valid = (deg[u] >= 2 || deg[v] >= 2);
    deg[u]++, deg[v]++;

    u = find(u); v = find(v);
    valid |= (ok[u] || ok[v]);
    val[++n] = w;
    p[n] = n; 
    ok[n] = 1;

    adj[n].push_back(u);
    p[u] = n;
    if(u != v) p[v] = n, adj[n].push_back(v), ok[n] = valid;
} //tạo reachability tree. res[u] là min của (ok[u] ? val[u] : inf) trên path từ root đến u
//đáp án là res[lca(x, y)] == inf ? -1 : res[lca(x, y)]
void dfs(int u, int mn){
    if(ok[u]) mn = min(mn, val[u]);
    res[u] = mn;
    for(auto v: adj[u]){
        h[v] = h[u] + 1;
        up[v][0] = u;
        dfs(v, mn);
    }
}
int lca(int u, int v){
    if(h[u] < h[v]) swap(u, v);
    for(int i = 0; i <= 18; i++){
        if((h[u] - h[v]) & (1 << i)) u = up[u][i];
    }

    if(u == v) return u;
    for(int i = 18; i >= 0; i--){
        if(up[u][i] != up[v][i]) u = up[u][i], v = up[v][i];
    }
    
    return up[u][0];
}
void init(int _n, int m, vector<int> u, vector<int> v, vector<int> w){
    vector<array<int, 3>> edge;
    for(int i = 0; i < m; i++) edge.push_back({w[i], u[i], v[i]});
     
    n = _n - 1;
    sort(edge.begin(), edge.end());
    for(int i = 0; i < _n; i++) p[i] = i;
     
    for(auto [w, u, v]: edge) merge(w, u, v);
     
    dfs(n, 1e9 + 1);
    
    for(int i = 1; i <= 18; i++){
        for(int j = 0; j <= n; j++) up[j][i] = up[up[j][i - 1]][i - 1];
    }
}
int getMinimumFuelCapacity(int x, int y){
    int l = lca(x, y);
    return (res[l] == 1e9 + 1 ? -1 : res[l]);
}
#ifdef LOCAL
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    
    int n, m; cin >> n >> m;
    vector<int> u(m), v(m), w(m);
    for(int i = 0; i < m; i++) cin >> u[i];
    for(int i = 0; i < m; i++) cin >> v[i];
    for(int i = 0; i < m; i++) cin >> w[i];
    init(n, m, u, v, w);
    int q; cin >> q;
    while(q--){
        int x, y; cin >> x >> y;
        cout << getMinimumFuelCapacity(x, y) << "\n";
    }
}
#endif
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...