Cod sursa(job #3031420)

Utilizator MihaiZ777MihaiZ MihaiZ777 Data 19 martie 2023 20:55:05
Problema Radiatie Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.66 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

ifstream fin("radiatie.in");
ofstream fout("radiatie.out");

const int MAX_N = 15005;

struct Edge {
    int a, b;
    int cost;
    inline bool operator < (const Edge& other) const {
        return cost < other.cost;
    }
};

int n, m, k;
int fathers[MAX_N];
int depth[MAX_N];
vector <Edge> edges;
vector <Edge> graph[MAX_N];
vector <Edge> opGraph[MAX_N];
int parent[MAX_N];

int ancestors[20][MAX_N];

void InitAPM() {
    sort(edges.begin(), edges.end());
    for (int i = 1; i <= n; i++) {
        fathers[i] = i;
        depth[i] = 1;
    }
}

int FindRoot(int node) {
    if (node == fathers[node]) {
        return node;
    }
    return fathers[node] = FindRoot(fathers[node]);
}

void Union(int a, int b, int cost) {
    int originalA = a;
    int originalB = b;
    a = FindRoot(a);
    b = FindRoot(b);

    if (depth[a] < depth[b]) {
        fathers[a] = b;
        graph[originalB].push_back({originalB, originalA, cost});
        opGraph[originalA].push_back({originalA, originalB, cost});
    }
    else if (depth[b] < depth[a]) {
        fathers[b] = a;
        graph[originalA].push_back({originalA, originalB, cost});
        opGraph[originalB].push_back({originalB, originalA, cost});
    }
    else {
        fathers[a] = b;
        depth[b]++;
        graph[originalB].push_back({originalB, originalA, cost});
        opGraph[originalA].push_back({originalA, originalB, cost});
    }
}

void BuildAPM() {
    InitAPM();

    for (Edge edge : edges) {
        if (FindRoot(edge.a) == FindRoot(edge.b)) {
            continue;
        }
        Union(edge.a, edge.b, edge.cost);
    }
}

void BuildDepths(int node, int d) {
    depth[node] = d;
    for (Edge newEdge : graph[node]) {
        BuildDepths(newEdge.b, d + 1);
    }
}

void BuildLCA() {
    for (int i = 1; i <= n; i++) {
        if (!graph[i].empty()) {
            for (Edge edge : graph[i]) {
                ancestors[0][edge.b] = i;
            }
        }
    }

    for (int e = 1; e < 19; e++) { 
        for (int node = 1; node <= n; node++) {
            ancestors[e][node] = ancestors[e - 1][ancestors[e - 1][node]];
        }
    }
    
    BuildDepths(FindRoot(1), 1);
}

int LCAQuery(int a, int b) {
    if (depth[a] < depth[b]) {
        swap(a, b);
    }
    int depthDiff = depth[a] - depth[b];
    for (int e = 0; e < 19; e++) {
        if (depthDiff & (1 << e)) {
            a = ancestors[e][a];
        }
    }

    if (a == b) {
        return a;
    }

    for (int e = 18; e >= 0; e--) {
        if (ancestors[e][a] != ancestors[e][b]) {
            a = ancestors[e][a];
            b = ancestors[e][b];
        }
    }

    return ancestors[0][a];
}

void DFSToNode(int node, int destination, int& maxValue) {
    if (node == destination) {
        return;
    }

    for (Edge edge : opGraph[node]) {
        maxValue = max(maxValue, edge.cost);
        DFSToNode(edge.b, destination, maxValue);
    }
}

void BuildAnswer() {
    for (int i = 1; i <= k; i++) {
        int a, b;
        fin >> a >> b;
        int root = LCAQuery(a, b);

        int maxValueToA = 0;
        DFSToNode(a, root, maxValueToA);

        int maxValueToB = 0;
        DFSToNode(b, root, maxValueToB);

        fout << max(maxValueToA, maxValueToB) << '\n';
    }
}

int main() {
    fin >> n >> m >> k;
    for (int i = 1; i <= m; i++) {
        int a, b, cost;
        fin >> a >> b >> cost;
        edges.push_back({a, b, cost});
    }

    BuildAPM();
    BuildLCA();
    BuildAnswer();
}