Cod sursa(job #3241596)

Utilizator filipinezulBrain Crash filipinezul Data 1 septembrie 2024 00:05:43
Problema Radiatie Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.16 kb
#include <bits/stdc++.h>
using namespace std;

class DisjointSet {
 private:
    vector<int> root;
    vector<int> size;

 public:
    DisjointSet(int n)
        : root(n + 1)
        , size(n + 1) {

        for (int node = 1; node <= n; ++node) {
            root[node] = node;
            size[node] = 1;
        }
    }

    int pathCompression(int node) {
        if (node == root[node]) {
            return node;
        }
        root[node] = pathCompression(root[node]);
        return root[node];
    }

    void unionByRank(int x, int y) {
        int rx = pathCompression(x), ry = pathCompression(y);
        if (rx != ry) {
            if (size[rx] <= size[ry]) {
                size[ry] += size[rx];
                root[rx] = ry;
            } else {
                size[rx] += size[ry];
                root[ry] = rx;
            }
        }
    }
};

class Task {
 public:
    void solve() {
        read_input();
        process();
        print_output();
    }

 private:
    int n, m, k;
    vector<tuple<int, int, int>> edges;

    vector<pair<int, int>> queries;
    vector<int> results;

    vector<vector<pair<int, int>>> adj;
    vector<vector<int>> up;

    vector<vector<int>> maxEdge;
    vector<int> depth;

    const int LOG = 15; // log2(15000) = 14

    void read_input() {
        ifstream fin("radiatie.in");
        fin >> n >> m >> k;
    
        edges.resize(m);
        queries.resize(k);

        adj.resize(n + 1);
        up.resize(n + 1, vector<int>(LOG));

        maxEdge.resize(n + 1, vector<int>(LOG));
        depth.resize(n + 1);

        for (int i = 0, a, b, c; i < m; ++i) {
            fin >> a >> b >> c;
            edges[i] = {c, a, b};
        }

        for (int i = 0, x, y; i < k; ++i) {
            fin >> x >> y;
            queries[i] = {x, y};
        }

        fin.close();
    }

    void process() {
        // Step 1: Sort edges by weight and create MST using Kruskal's algorithm
        sort(edges.begin(), edges.end());
        DisjointSet dsu(n);

        for (auto [c, a, b] : edges) {
            if (dsu.pathCompression(a) != dsu.pathCompression(b)) {
                dsu.unionByRank(a, b);
                adj[a].emplace_back(b, c);
                adj[b].emplace_back(a, c);
            }
        }

        // Step 2: Preprocess LCA and max edge info
        dfs(1, 0, 0, 0);

        // Step 3: Process each query
        for (auto [x, y] : queries) {
            results.push_back(getMaxEdgeInPath(x, y));
        }
    }

    void dfs(int node, int parent, int d, int w) {
        depth[node] = d;
        up[node][0] = parent;
        maxEdge[node][0] = w;

        for (int i = 1; i < LOG; ++i) {
            up[node][i] = up[up[node][i - 1]][i - 1];
            maxEdge[node][i] = max(maxEdge[node][i - 1], maxEdge[up[node][i - 1]][i - 1]);
        }

        for (auto [neighbor, weight] : adj[node]) {
            if (neighbor != parent) {
                dfs(neighbor, node, d + 1, weight);
            }
        }
    }

    int getMaxEdgeInPath(int u, int v) {
        if (depth[u] < depth[v]) swap(u, v);

        int maxEdgeInPath = 0;

        // Bring u and v to the same depth
        for (int i = LOG - 1; i >= 0; --i) {
            if (depth[u] - (1 << i) >= depth[v]) {
                maxEdgeInPath = max(maxEdgeInPath, maxEdge[u][i]);
                u = up[u][i];
            }
        }

        if (u == v) {
            return maxEdgeInPath;
        }

        // Bring u and v to their LCA
        for (int i = LOG - 1; i >= 0; --i) {
            if (up[u][i] != up[v][i]) {
                maxEdgeInPath = max({maxEdgeInPath, maxEdge[u][i], maxEdge[v][i]});
                u = up[u][i];
                v = up[v][i];
            }
        }

        // Final step to reach LCA
        return max({maxEdgeInPath, maxEdge[u][0], maxEdge[v][0]});
    }

    void print_output() {
        ofstream fout("radiatie.out");

        for (int result : results) {
            fout << result << "\n";
        }

        fout.close();
    }
};

int main() {
    ios::sync_with_stdio(false);
    auto* task = new (nothrow) Task();

    if (!task) {
        cerr << "new failed\n";
        return -1;
    }

    task->solve();
    delete task;

    return 0;
}