Cod sursa(job #3125533)

Utilizator Razvan48Capatina Razvan Nicolae Razvan48 Data 3 mai 2023 17:23:40
Problema Radiatie Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 5.25 kb
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

/// APM + stramosi + LCA
/// De mentionat ca nu e neaparat conex graful primit din input.

const int NMAX = 15000;
const int LOGMAX = 14;

struct Muchie
{
    int x;
    int y;
    int c;

    Muchie() = default;

    Muchie(int x, int y, int c) :
        x(x), y(y), c(c) {};

    bool operator < (const Muchie& other) const { return this->c < other.c; }
};

vector<Muchie> muchii;
int tata[1 + NMAX];
int h[1 + NMAX];

int getTata(int x)
{
    if (x != tata[x])
        tata[x] = getTata(tata[x]);

    return tata[x];
}

void unifica(int x, int y)
{
    int tataX = getTata(x);
    int tataY = getTata(y);

    if (tataX != tataY)
    {
        if (h[tataX] > h[tataY])
            tata[tataY] = tataX;
        else if (h[tataY] > h[tataX])
            tata[tataX] = tataY;
        else
        {
            tata[tataY] = tataX;
            ++h[tataX];
        }
    }
}

vector<pair<int, int>> graf[1 + NMAX];

bool vizitat[1 + NMAX];
int primaAparitie[1 + NMAX];
int adancime[1 + NMAX];
vector<int> liniarizare;
pair<int, int> stramosi[1 + NMAX][1 + LOGMAX];
int rmq[1 + 2 * NMAX - 1][1 + LOGMAX];
int log2Max[1 + 2 * NMAX - 1];

void dfs(int nod, int adanc, int tata, int costTata)
{
    vizitat[nod] = true;
    adancime[nod] = adanc;
    liniarizare.emplace_back(nod);
    primaAparitie[nod] = (int)liniarizare.size() - 1;
    stramosi[nod][0] = make_pair(tata, costTata);

    for (int i = 0; i < graf[nod].size(); ++i)
    {
        if (!vizitat[graf[nod][i].first])
        {
            dfs(graf[nod][i].first, adanc + 1, nod, graf[nod][i].second);
            liniarizare.emplace_back(nod);
        }
    }
}

void preCalcRMQ()
{
    int putere2 = 1;
    int exp2 = 0;

    for (int i = 1; i < liniarizare.size(); ++i)
    {
        if (putere2 * 2 <= i)
        {
            putere2 *= 2;
            ++exp2;
        }

        log2Max[i] = exp2;
    }

    for (int i = 1; i < liniarizare.size(); ++i)
        rmq[i][0] = liniarizare[i];

    for (int l = 1; l <= LOGMAX; ++l)
    {
        for (int i = 1; i + (1 << l) - 1 < liniarizare.size(); ++i)
        {
            if (adancime[rmq[i][l - 1]] < adancime[rmq[i + (1 << (l - 1))][l - 1]])
                rmq[i][l] = rmq[i][l - 1];
            else
                rmq[i][l] = rmq[i + (1 << (l - 1))][l - 1];
        }
    }
}

int LCA(int x, int y)
{
    if (primaAparitie[x] > primaAparitie[y])
        swap(x, y);

    if (adancime[rmq[primaAparitie[x]][log2Max[primaAparitie[y] - primaAparitie[x] + 1]]] <
        adancime[rmq[primaAparitie[y] - (1 << log2Max[primaAparitie[y] - primaAparitie[x] + 1]) + 1][log2Max[primaAparitie[y] - primaAparitie[x] + 1]]]
        )
        return rmq[primaAparitie[x]][log2Max[primaAparitie[y] - primaAparitie[x] + 1]];
    else
        return rmq[primaAparitie[y] - (1 << log2Max[primaAparitie[y] - primaAparitie[x] + 1]) + 1][log2Max[primaAparitie[y] - primaAparitie[x] + 1]];
}

void preCalcStramosi(int n)
{
    for (int l = 1; l <= LOGMAX; ++l)
        for (int i = 1; i <= n; ++i)
            stramosi[i][l] = make_pair(stramosi[stramosi[i][l - 1].first][l - 1].first, max(stramosi[i][l - 1].second, stramosi[stramosi[i][l - 1].first][l - 1].second));
}

int main()
{
    ifstream in("radiatie.in");
    ofstream out("radiatie.out");

    ios_base::sync_with_stdio(false);
    in.tie(nullptr);

    int n, m, k;
    in >> n >> m >> k;

    for (int i = 1; i <= m; ++i)
    {
        int a, b, c;
        in >> a >> b >> c;

        muchii.emplace_back(a, b, c);
    }

    for (int i = 1; i <= n; ++i)
    {
        tata[i] = i;
        h[i] = 1;
    }

    sort(muchii.begin(), muchii.end());

    for (int i = 0; i < muchii.size(); ++i)
    {
        if (getTata(muchii[i].x) != getTata(muchii[i].y))
        {
            unifica(muchii[i].x, muchii[i].y);

            graf[muchii[i].x].emplace_back(muchii[i].y, muchii[i].c);
            graf[muchii[i].y].emplace_back(muchii[i].x, muchii[i].c);
        }
    }

    liniarizare.emplace_back(0);
    for (int i = 1; i <= n; ++i) /// GRAFUL NU E NEAPARAT CONEX (APM-ul ESTE O PADURE DE APM)
        if (!vizitat[i])
            dfs(i, 1, 0, 0);
    preCalcRMQ();
    preCalcStramosi(n);

    for (int j = 1; j <= k; ++j)
    {
        int x, y;
        in >> x >> y;

        int lca = LCA(x, y);

        int maxim = 0;

        int numarPasi = adancime[x] - adancime[lca];
        int stareCurenta = x;

        for (int i = LOGMAX; i >= 0; --i)
        {
            if (((1 << i) & numarPasi))
            {
                maxim = max(maxim, stramosi[stareCurenta][i].second);
                stareCurenta = stramosi[stareCurenta][i].first;
            }
        }

        numarPasi = adancime[y] - adancime[lca];
        stareCurenta = y;

        for (int i = LOGMAX; i >= 0; --i)
        {
            if (((1 << i) & numarPasi))
            {
                maxim = max(maxim, stramosi[stareCurenta][i].second);
                stareCurenta = stramosi[stareCurenta][i].first;
            }
        }

        out << maxim << '\n';
    }

    in.close();
    out.close();

    return 0;
}