Cod sursa(job #1376022)

Utilizator diana97Diana Ghinea diana97 Data 5 martie 2015 15:32:31
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.45 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

ifstream f ("radiatie.in");
ofstream g ("radiatie.out");

struct Muchie {
    int a, b, cost;
    Muchie(int a, int b, int cost) {
        this->a = a;
        this->b = b;
        this->cost = cost;
    };
};

const int NMAX = 15000 + 1, MMAX = 30000 + 1;
const int LOGMAX = 16;

int n, m, q;
int e, nre;
int tata[NMAX], rang[NMAX], eticheta[NMAX], etichetat[NMAX], prima[NMAX], niv[NMAX];
int lg2[2 * NMAX];
int rmq[LOGMAX][2 * NMAX], t[LOGMAX][NMAX], best[LOGMAX][NMAX];
vector <Muchie> muchii;
vector <int> arb[NMAX], cost[NMAX];

void citeste() {
    int a, b, c;
    f >> n >> m >> q;
    for (int i = 1; i <= m; i++) {
        f >> a >> b >> c;
        muchii.push_back(Muchie(a, b, c));
    }
}

inline bool comp(Muchie a, Muchie b) {
    return a.cost < b.cost;
}

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

int radacina(int x) {
    if (x == tata[x]) return x;
    tata[x] = radacina(tata[x]);
    return tata[x];
}

void uneste(int a, int b) {
    a = radacina(a);
    b = radacina(b);
    if (rang[b] > rang[a]) tata[a] = b;
    else tata[b] = a;
    if (rang[a] == rang[b]) rang[a]++;
}

bool sunt_unite(int a, int b) {
    a = radacina(a);
    b = radacina(b);
    return (a == b);
}

void build_apm() {
    int a, b, c;
    initializeaza();
    sort(muchii.begin(), muchii.end(), comp);

    for (int i = 0; i < m; i++) {
        a = muchii[i].a;
        b = muchii[i].b;
        c = muchii[i].cost;

        if (sunt_unite(a, b)) continue;
        uneste(a, b);

        arb[a].push_back(b);
        arb[b].push_back(a);

        cost[a].push_back(c);
        cost[b].push_back(c);
    }
}

void liniarizare(int nod) {
    int l = arb[nod].size(), fiu;

    eticheta[nod] = ++e;
    etichetat[e] = nod;
    rmq[0][++nre] = eticheta[nod];
    prima[nod] = nre;

    for (int i = 0; i < l; i++) {
        fiu = arb[nod][i];
        if (fiu == t[0][nod]) continue;

        t[0][fiu] = nod;
        best[0][fiu] = cost[nod][i];
        niv[fiu] = niv[nod] + 1;

        liniarizare(fiu);
        rmq[0][++nre] = eticheta[nod];
    }
}

void precalculeaza() {
    for (int i = 2; i <= nre; i++) lg2[i] = lg2[i / 2] + 1;
    int l;

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

inline int lca(int a, int b) {
    a = prima[a];
    b = prima[b];
    if (a > b) swap(a, b);
    int l, secv1, secv2;
    l = lg2 [b - a + 1];
    secv1 = a;
    secv2 = b - (1 << l) + 1;
    return etichetat[min(rmq[l][secv1], rmq[l][secv2])];
}

void dinamica() {
    int i, j, ant;

    for (int i = 1; (1 << i) <= n; i++)
        for (int j = 1; j <= n; j++) {
            ant = t[i - 1][j];
            t[i][j] = t[i - 1][ant];
            best[i][j] = max(best[i - 1][j], best[i - 1][ant]);
        }
}

int rez(int x, int y) {
    int p = niv[x] - niv[y], sol = 0;
    for (int i = 0; (1 << i) <= p; i++)
        if (p & (1 << i)) {
            sol = max(sol, best[i][x]);
            x = t[i][x];
        }
    return sol;
}

void rezolva() {
    int a, b, l;
    while(q--) {
        f >> a >> b;
        l = lca(a, b);
        //cout << l << ' ';
        g << max(rez(a, l), rez(b, l)) << '\n';
    }
}

int main() {
    citeste();
    build_apm();
    niv[1] = 1;
    liniarizare(1);
    dinamica();
    rezolva();
}