Cod sursa(job #1787612)

Utilizator oldatlantianSerban Cercelescu oldatlantian Data 24 octombrie 2016 20:38:34
Problema Radiatie Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.48 kb
#include <bits/stdc++.h>
using namespace std;

const int SPQR = 15005,
          LG = 20;

struct PII {
    int v, c; };

struct EDG {
    int u, v, c;
    bool operator < (const EDG &arg) const {
        return c < arg.c; } };

int n, m;
int far[LG][SPQR], mxe[LG][SPQR], lvl[SPQR], unf[SPQR], usz[SPQR];
vector<PII> g[SPQR];
vector<EDG> edg;

void dfs(int u) {
    for(auto i: g[u]) if(!lvl[i.v]) {
        lvl[i.v] = lvl[u] + 1;
        far[0][i.v] = u;
        mxe[0][i.v] = i.c;
        dfs(i.v); } }

bool same(int u, int v) {
    while(unf[u]) u = unf[u];
    while(unf[v]) v = unf[v];

    return (u == v); }

void join(int u, int v) {
    while(unf[u]) u = unf[u];
    while(unf[v]) v = unf[v];

    if(usz[u] > usz[v]) {
        usz[u]+= usz[v];
        unf[v] = u; }
    else {
        usz[v]+= usz[u];
        unf[u] = v; } }

void make_apm(void) {
    sort(edg.begin(), edg.end());

    for(int i=1; i<=n; ++i)
        usz[i] = 1;

    for(auto i: edg) if(!same(i.u, i.v)) {
        join(i.u, i.v);
        g[i.u].push_back({i.v, i.c});
        g[i.v].push_back({i.u, i.c}); } }

void make_anc(void) {
    dfs(1);
    for(int lg=1; (1<<lg) < SPQR; ++lg) {
        for(int i=1; i<=n; ++i) {
            far[lg][i] = far[lg-1][far[lg-1][i]];
            mxe[lg][i] = max(mxe[lg-1][i], mxe[lg-1][far[lg-1][i]]); } } }

int anc(int x, int l) {
    for(int i=0; l; l>>=1, ++i) if(l&1) {
        x = far[i][x]; }

    return x; }

int lca(int x, int y) {
    if(lvl[x] > lvl[y]) {
        x = anc(x, lvl[x] - lvl[y]); }
    else {
        y = anc(y, lvl[y] - lvl[x]); }

    if(x == y) return x;

    for(int lg=17; lg>=0; --lg) {
        if(far[lg][x] != far[lg][y]) {
            x = far[lg][x];
            y = far[lg][x]; } }

    return anc(x, 1); }

int min_lca(int x, int y) {
    int mx, dl, ffr;

    if(x == y)
        return 0;

    ffr = lca(x, y);
    mx = -1;

    dl = lvl[x] - lvl[ffr];
    for(int i=0; dl; ++i, dl>>=1) if(dl&1) {
        mx = max(mx, mxe[i][x]);
        x = far[i][x]; }

    dl = lvl[y] - lvl[ffr];
    for(int i=0; dl; ++i, dl>>=1) if(dl&1) {
        mx = max(mx, mxe[i][y]);
        y = far[i][y]; }

    assert(x==ffr && y==ffr);

    return mx; }

int main(void) {
    ifstream fi("radiatie.in");
    ofstream fo("radiatie.out");
    int q, x, y;

    fi >> n >> m >> q;
    edg.resize(m);

    for(auto &i: edg)
        fi >> i.u >> i.v >> i.c;

    lvl[1] = 1;

    make_apm();
    make_anc();

    while(q--) {
        fi >> x >> y;
        fo << min_lca(x, y) << '\n'; }

    return 0; }