Cod sursa(job #3207274)

Utilizator amcbnCiobanu Andrei Mihai amcbn Data 25 februarie 2024 18:21:54
Problema Radiatie Scor 30
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.36 kb
#include <bits/stdc++.h>
using namespace std;
const char nl = '\n';
const char sp = ' ';
const int inf = 0x3f3f3f3f;
const int mod = 30011;
const char out[2][4]{ "NO", "YES" };
#define all(a) a.begin(), a.end()
using ll = long long;
ifstream fin("radiatie.in");
ofstream fout("radiatie.out");

const int nmax = 15000;
const int lgmax = 14;
int n, m, q;
vector<pair<int, int>> g[nmax + 5];
int depth[nmax + 5]{ 0 };
int tin[nmax + 5]{ 0 };
int tout[nmax + 5]{ 0 };
int timer = 0;
int t[lgmax + 1][nmax + 5]{ 0 };
int rmq[lgmax + 1][nmax + 5]{ 0 };

void compute(int u, int p = -1) {
    tin[u] = ++timer;
    for (auto& e : g[u]) {
        int v = e.first, w = e.second;
        if (v == p) {
            continue;
        }
        depth[v] = depth[u] + 1;
        t[0][v] = u;
        rmq[0][v] = w;
        for (int p = 1; p <= lgmax; ++p) {
            if (t[p - 1][v] == 0 || t[p - 1][t[p - 1][v]] == 0) {
                break;
            }
            t[p][v] = t[p - 1][t[p - 1][v]];
            rmq[p][v] = max(rmq[p - 1][v], rmq[p - 1][t[p - 1][v]]);
        }
        compute(v, u);
    }
    tout[u] = ++timer;
}

bool is_ancestor(int u, int v) {
    return tin[u] <= tin[v] && tout[v] <= tout[u];
}

pair<int, int> kth(int u, int k) {
    pair<int, int> res(u, 0);
    for (int p = 0; (1 << p) <= k; ++p) {
        if ((k >> p) & 1) {
            res.second = max(res.second, rmq[p][res.first]);
            res.first = t[p][res.first];
        }
    }
    return res;
}

int query(int u, int v) {
    if (depth[u] > depth[v]) {
        swap(u, v);
    }
    int ans = 0;
    if (depth[u] != depth[v]) {
        tie(v, ans) = kth(v, depth[v] - depth[u]);
    }
    if (u == v) {
        return ans;
    }
    for (int p = lgmax; p >= 0; --p) {
        if (t[p][u] != t[p][v]) {
            ans = max(ans, max(rmq[p][u], rmq[p][v]));
            u = t[p][u];
            v = t[p][v];
        }
    }
    return ans;
}

struct DisjointSetUnion {
    int size;
    DisjointSetUnion(int size) {
        this->size = size;
        p.resize(size + 1);
        sz.resize(size + 1);
        for (int i = 1; i <= size; ++i) {
            p[i] = i, sz[i] = 1;
        }
    }
    int find(int x) {
        return p[x] == x ? x : (p[x] = find(p[x]));
    }
    void merge(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) {
            return;
        }
        if (sz[x] < sz[y]) {
            swap(x, y);
        }
        p[y] = x;
        sz[x] += sz[y];
        sz[y] = 0;
    }
    bool connected(int x, int y) {
        return find(x) == find(y);
    }
private:
    vector<int> p, sz;
};

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    fin >> n >> m >> q;
    vector<tuple<int, int, int>> edges;
    for (int i = 1; i <= m; ++i) {
        int u, v, w;
        fin >> u >> v >> w;
        edges.push_back({ w, u, v });
    }
    sort(all(edges));
    DisjointSetUnion tree(n);
    for (auto& edge : edges) {
        int u = get<1>(edge), v = get<2>(edge), w = get<0>(edge);
        if (tree.connected(u, v)) {
            continue;
        }
        tree.merge(u, v);
        g[u].push_back({ v, w });
        g[v].push_back({ u, w });
    }
    compute(1);
    while (q--) {
        int u, v;
        fin >> u >> v;
        fout << query(u, v) << nl;
    }
}