Cod sursa(job #1020556)

Utilizator ericptsStavarache Petru Eric ericpts Data 2 noiembrie 2013 11:04:05
Problema Radiatie Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.78 kb
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#include <utility>

using namespace std;

const int MAX_N = 15100;
const int LG = 16;

struct edge{
    int a, b, cost;
};

bool comp(const edge &a, const edge &b){
    return a.cost < b.cost;
}

edge E[MAX_N * 2];
vector< pair<int ,int> > G[MAX_N];

char buff[32677];
int n,m,k;

int TT[MAX_N];
int under[MAX_N];

inline int father(const int node){
    if(TT[node] == 0)
        return node;
    const int up = father(TT[node]);
    TT[node] = up;
    return up;
}

bool unite(const int a, const int b){
    const int a_up = father(a),
              b_up = father(b);
    if(a_up == b_up)
        return false;
    if(under[a_up] >= under[b_up]){
        under[a_up] += under[b_up] + 1;
        TT[b_up] = a_up;
    } else {
        under[b_up] += under[a_up] + 1;
        TT[a_up] = b_up;
    }
    return true;
}

int up[LG][MAX_N];
int cost[LG][MAX_N];

void ancestor(){
    for(int i = 1 ; i < LG ; ++i){
        for(int j = 1 ; j <= n ; ++ j){
            up[i][j] = up[i-1][up[i-1][j]];
            cost[i][j] = cost[i-1][j];
            const int upper = cost[i-1][up[i-1][j]];
            if(upper > cost[i][j])
                cost[i][j] = upper;
        }
    }
}

int line[MAX_N * 2];
int fst[MAX_N];
int lvl[MAX_N];
int CR;
bool viz[MAX_N];

void DFS(const int node){
    ++CR;
    fst[node] = CR;
    viz[node] = 1;
    line[CR] = node;
    for(unsigned int i = 0 ; i < G[node].size() ; ++i){
        const int son = G[node][i].first,
                  price = G[node][i].second;
        if(viz[son])
            continue;
        up[0][son] = node;
        cost[0][son] = price;
        lvl[son] = lvl[node] + 1;
        DFS(son);
        ++CR;
        line[CR] = node;
    }
}

int RMQ[MAX_N * 2][LG];
int lg[MAX_N * 2];

void build_RMQ(){
    for(int i = 2 ; i <= CR ; ++i)
        lg[i] = lg[i/2] + 1;
    for(int i = 1 ; i <= CR ; ++i)
        RMQ[i][0] = lvl[line[i]];
    for(int j = 1 ; j < LG ; ++j){
        for(int i = 1 ; i + (1 << j) - 1 <= CR ; ++i){
            const int one = RMQ[i][j-1],
                      other = RMQ[i + (1 << j-1)][j-1];
            RMQ[i][j] = one;
            if(other < RMQ[i][j])
                RMQ[i][j] = other;
        }
    }
}

int RMQuery(const int lo, const int hi){
    const int delta = (hi - lo);
    const int p2 = lg[delta];
    const int one = RMQ[lo][p2],
              other = RMQ[hi + 1 - (1 << p2)][p2];
    return min(one, other);
}

int LCA(const int a, const int b){
    const int one = fst[a], two = fst[b];
    if(one <= two)
        return RMQuery(one, two);
    else return RMQuery(two, one);
}

int go_up(const int origin, const int levels){
    int now = origin,
        left = levels,
        ret = 0;
    for(int i = LG - 1 ; i >= 0 && levels ; --i){
        while((1 << i) <= left){
            left -= 1 << i;
            const int path = cost[i][now];
            if(path > ret)
                ret = path;
            now = up[i][now];
        }
    }
    return ret;
}

void queries(){
    while(k--){
        int a,b;
        scanf("%d%d", &a, &b);
        const int root = LCA(a, b);
        const int one = go_up(a, lvl[a] - root),
                  other = go_up(b, lvl[b] - root);
        printf("%d\n", max(one, other));
    }
}

int main(){
    freopen("radiatie.in", "r", stdin);
    freopen("radiatie.out", "w", stdout);
    setvbuf(stdin, buff, _IOFBF, sizeof(buff));
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 0 ; i < m ; ++i)
        scanf("%d%d%d", &E[i].a, &E[i].b, &E[i].cost);
    sort(E, E + m, comp);
    for(int i = 0 ; i < m ; ++i){
        if(unite(E[i].a, E[i].b)){
            G[E[i].a].push_back(make_pair(E[i].b, E[i].cost));
            G[E[i].b].push_back(make_pair(E[i].a, E[i].cost));
        }
    }
    DFS(1);
    build_RMQ();
    ancestor();
    queries();
}