Cod sursa(job #2961219)

Utilizator matei.tudoseMatei Tudose matei.tudose Data 5 ianuarie 2023 23:41:41
Problema Radiatie Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.85 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;

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;

class TreeEdge
{
public:
    int node, cost;
};

vector<TreeEdge> Tree[MaxN];

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

int find_root(const 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()
{ /// Minimum Spanning Pom
    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);
        Tree[it.n1].push_back({it.n2, it.cost});
        Tree[it.n2].push_back({it.n1, it.cost});
    }
}

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

    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 dfs(int curr, int level)
{
    lvl[curr] = level;

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

        anc_table[0][nxt.node] = curr;
        max_table[0][nxt.node] = nxt.cost;
        dfs(nxt.node, 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])
        {
            max_tunnel = max3(max_tunnel, max_table[i][node1], max_table[i][node2]);
            node1 = anc_table[i][node1];
            node2 = anc_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();

    for (int i = 1; i <= n; ++i)
    {
        if (lvl[i])
        {
            continue;
        }

        dfs(i, 1);
    }

    AncTable_init();

    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;
}