Cod sursa(job #3340514)

Utilizator NeamtuMateiNeamtu Matei-Constantin NeamtuMatei Data 14 februarie 2026 18:45:21
Problema Radiatie Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.38 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;

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

typedef pair<int, int> pii;
const int MAXN = 15e3;
const int MAXM = 3e4;
const int MAXLOG = 15;

struct muchie {
    int cost;
    int x, y;
};
// 1. determinarea APM
// 2. aleg o radacina random si fac LCA cu RMQ
// 3. am ceva matrice m[i][j] = costul maxim dintre nodul i si stramosul lui, 2^j sa fac toate queryurile O(1)

int n, m, qrs, x, y, z, idx_apm, ek;
int repr[MAXN+1], tata[MAXN+1], level[MAXN+1];

int euler[2*MAXN+1], nivele[2*MAXN+1];
int first_app[MAXN+1]; // prima aparitie a nodului i in reprezentarea euler
bool viz[MAXN+1];

int lg2[MAXN+1];
int rmq[MAXLOG][2*MAXN+1];

vector<pii> grafAPM[MAXN+1];
muchie muchii[MAXM+1], APM[MAXN+1];
map<pii, int> muchie_cost;


int radacina(int nod) {
    if (repr[nod] == nod)
        return nod;
    return repr[nod] = radacina(repr[nod]);
}

void combine(int r1, int r2) {
    if (r1 < r2)
        repr[r2] = repr[r1];
    else
        repr[r1] = repr[r2];
}

void kruskal() {
    for (int i = 1; i <= n; i++)
        repr[i] = i;

    sort(muchii + 1, muchii + m + 1, [](muchie a, muchie b){
        return a.cost < b.cost;
    });

    for (int i = 1; i <= m; i++) {
        int x = muchii[i].x, y = muchii[i].y;
        int cost = muchii[i].cost;

        int r1 = radacina(x);
        int r2 = radacina(y);

        if (r1 != r2) {
            APM[++idx_apm] = muchii[i];
            combine(r1, r2);
        }
    }
}


void build_grafAPM() {
    for (int i = 1; i < n; i++) {
        int x = APM[i].x, y = APM[i].y;
        int z = APM[i].cost;

        grafAPM[x].push_back({y, z});
        grafAPM[y].push_back({x, z});
    }
}

void dfs_euler(int nod, int nivel, int padre) {
    ++ek;
    nivele[ek] = nivel;
    euler[ek] = nod;
    level[nod] = nivel;

    viz[nod] = true;
    first_app[nod] = ek;
    tata[nod] = padre;

    for (auto e: grafAPM[nod])
        if (!viz[e.first]) {
            dfs_euler(e.first, nivel + 1, nod);

            ++ek;
            nivele[ek] = nivel;
            euler[ek] = nod;
        }
}


void build_RMQ() {
    lg2[0] = lg2[1] = 0;
    for (int i = 2; i <= MAXN; i++)
        lg2[i] = lg2[i / 2] + 1;

    for (int i = 1; i <= ek; i++)
        rmq[0][i] = nivele[i];

    for (int i = 1; i <= lg2[ek]; i++)
        for (int j = 1; j <= ek - (1 << i) + 1; j++) {
            rmq[i][j] = min(
                rmq[i - 1][j],
                rmq[i - 1][j + (1 << (i - 1))]
            );
        }
}

int LCA(int nod1, int nod2) {
    int st = min( first_app[nod1], first_app[nod2] );
    int dr = max( first_app[nod1], first_app[nod2] );

    int lgk = lg2[dr - st];

    int minRMQ = min(
        rmq[lgk][st],
        rmq[lgk][dr - (1 << lgk) + 1]
    );

    return first_app[ minRMQ ];
}

int mat[MAXN+1][MAXLOG+1];
void build_mat() {
    for (int i = 1; i <= n; i++) {
        int nod = i, ancestor = tata[nod];
        int j = 1;

        while (tata[nod]) {
            mat[i][j] = max( muchie_cost[{nod, tata[nod]}], mat[i][j-1] );
            nod = tata[nod];
            j++;
        }
    }
}


int main() {
    in >> n >> m >> qrs;
    for (int i = 1; i <= m; i++) {
        in >> x >> y >> z;

        muchii[i] = {z, x, y};
        muchie_cost[{x, y}] = muchie_cost[{y, x}] = z;
    }

    // determinam APM cu kruskal DSU
    idx_apm = 0;
    kruskal();

    // construim reprezentarea euler
    ek = 0;
    build_grafAPM();
    dfs_euler(1, 1, 0); // luam arbitrar radacina APM-ului 1
                     // construim simultan si vectorul de tati

    // construim RMQ
    build_RMQ();

    // construim matricea drumurilor maxime
    // mat[i][j] = valoarea maxima a drumului de la nodul i la stramosul al j-lea (j = 1 fiind tatal lui i)
    build_mat();

    // raspundem query-urilor
    for (int i = 1; i <= qrs; i++) {
        in >> x >> y;

        int lca = LCA(x, y);
        int dist_x_lca = abs(level[x] - level[lca]);
        int dist_y_lca = abs(level[y] - level[lca]);

        int maxroad_x_lca = mat[x][dist_x_lca];
        int maxroad_y_lca = mat[y][dist_y_lca];

        out << max(maxroad_x_lca, maxroad_y_lca) << '\n';
    }

    return 0;
}