Cod sursa(job #1657154)

Utilizator BrandonChris Luntraru Brandon Data 20 martie 2016 11:00:50
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.02 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

ifstream cin("radiatie.in");
ofstream cout("radiatie.out");

const int MaxM = 300005, LogMaxM = 20, MaxN = 15005;

vector <int> Tree[MaxN];

int dsu_depth[MaxN], father[MaxN], anc_table[LogMaxM][MaxN], max_table[LogMaxM][MaxN], lvl[MaxN];
int n, m, k, log2n, msp_root, max_tunnel;

class Edge {
public:
    int n1, n2, cost;
};

vector <Edge> edg, msp_list;

void dsu_init() {
    for(int i = 1; i <= n; ++i) {
        dsu_depth[i] = 1;
        father[i] = i;
    }
}

int find_root(int node) {
    if(node == father[node]) {
        return node;
    }

    return father[node] = find_root(father[node]);
}

void dsu_merge(const int &node1, const int &node2) {
    int root1 = find_root(node1);
    int root2 = find_root(node2);

    if(dsu_depth[root1] < dsu_depth[root2]) {
        father[root1] = root2;
    }
    else if(dsu_depth[root2] < dsu_depth[root1]) {
        father[root2] = root1;
    }
    else {
        father[root2] = root1;
        ++dsu_depth[root1];
    }
}

inline bool EdgeSort(const Edge &a, const Edge &b) {
    return a.cost < b.cost;
}

void MSP() {
    sort(edg.begin(), edg.end(), EdgeSort);

    for(auto it: edg) {
        if(find_root(it.n1) == find_root(it.n2)) {
            continue;
        }

        dsu_merge(it.n1, it.n2);
        msp_list.push_back({it.n1, it.n2, it.cost});
    }
}

void AncTable_init() {
    for(auto it: msp_list) {
        Tree[it.n1].push_back(it.n2);
        Tree[it.n2].push_back(it.n1);

        if(anc_table[0][it.n2]) {
            anc_table[0][it.n1] = it.n2;
            max_table[0][it.n1] = it.cost;
        }
        else/* if(anc_table[0][it.n1])*/ {
            anc_table[0][it.n2] = it.n1;
            max_table[0][it.n2] = it.cost;
        }
    }

    for(int i = 1; i <= n; ++i) {
        if(!anc_table[0][i]) {
            anc_table[0][i] = i;
            msp_root = i;
            break;
        }
    }

    for(int i = 1; i <= log2n; ++i) {
        for(int j = 1; j <= n; ++j) {
            anc_table[i][j] = anc_table[i - 1][anc_table[i - 1][j]];
            max_table[i][j] = max(max_table[i - 1][j], max_table[i - 1][anc_table[i - 1][j]]);
        }
    }
}

void lvl_init(int node, int level) {
    lvl[node] = level;

    for(auto nxt: Tree[node]) {
        if(lvl[nxt]) {
            continue;
        }

        lvl_init(nxt, level + 1);
    }
}

void EqLevel(int &nodeLo, int &nodeHi) {
    if(lvl[nodeLo] < lvl[nodeHi]) {
        swap(nodeLo, nodeHi);
    }

    int diff = lvl[nodeLo] - lvl[nodeHi];

    for(int i = log2(diff); i >= 0 and diff; --i) {
        if(diff - (1 << i) >= 0) {
            diff -= (1 << i);
            max_tunnel = max(max_tunnel, max_table[i][nodeLo]);
            nodeLo = anc_table[i][nodeLo];
        }
    }
}

inline int max3(int a, int b, int c) {
    int ans = a;

    if(b > ans) {
        ans = b;
    }

    if(c > ans) {
        ans = c;
    }

    return ans;
}

void LCA(int node1, int node2) {
    if(node1 == node2) {
        return;
    }

    for(int i = log2n; i >= 0; --i) {
        if(anc_table[i][node1] != anc_table[i][node2]) {
            node1 = anc_table[i][node1];
            node2 = anc_table[i][node2];
            max_tunnel = max3(max_tunnel, max_table[i][node1], max_table[i][node2]);
        }
    }

    max_tunnel = max3(max_tunnel, max_table[0][node1], max_table[0][node2]);
}

int main() {
    cin >> n >> m >> k;
    log2n = log2(n);

    for(int i = 1; i <= m; ++i) {
        int a, b, d;
        cin >> a >> b >> d;
        edg.push_back({a, b, d});
    }

    dsu_init();
    MSP();
    AncTable_init();
    lvl_init(msp_root, 1);

    for(int i = 1; i <= k; ++i) {
        int node1, node2;
        max_tunnel = 0;
        cin >> node1 >> node2;
        EqLevel(node1, node2);
        LCA(node1, node2);
        cout << max_tunnel << '\n';
    }

    return 0;
}