Cod sursa(job #879134)

Utilizator deneoAdrian Craciun deneo Data 14 februarie 2013 23:40:15
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.92 kb
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <fstream>
using namespace std;

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

#define MAXN 30001
#define INF 0x3f3f3f3f

int N, M, K, arb[MAXN], used[MAXN], sir[2 * MAXN], first[MAXN], rmq[20][2 * MAXN], stramosi[20][MAXN], strmin[20][MAXN], dad[MAXN], cost[MAXN], adan[MAXN];

struct muchia {
    int c, x, y;
};

vector<muchia> muchie;
vector< pair<int, int> > graph[MAXN];

void initPADURE() {
    for (int i = 1; i <= N; ++i)
        arb[i] = i;
}

int getRADACINA(int nod) {
    if (arb[nod] == nod)
        return nod;
    arb[nod] = getRADACINA(arb[nod]);
    return arb[nod];
}

void uneste(int nod1, int nod2) {
    arb[arb[nod1]] = arb[nod2];
}

muchia make_muchia(int x, int y, int c) {
    muchia a;
    a.x = x;
    a.y = y;
    a.c = c;
    return a;
}

bool cmp(muchia a, muchia b) {
    return a.c < b.c;
}

void doDFS(int nod, int dist) {
    used[nod] = 1;
    sir[++sir[0]] = nod;
    first[nod] = sir[0];

    adan[nod] = dist;

    for (int i = 0; i < graph[nod].size(); ++i) {
        int node = graph[nod][i].first;
        if (!used[node]) {
            doDFS(node, dist + 1);
            sir[++sir[0]] = nod;
        }
    }
}

void doRMQ() {
    for (int i = 1; i <= sir[0]; ++i)
        rmq[0][i] = sir[i];

    for (int i = 1; (1 << i) <= sir[0]; ++i)
        for (int j = 1; j + (1 << i) - 1 <= sir[0]; ++j)
            rmq[i][j] = min (rmq[i - 1][j], rmq[i - 1][j + (1 << (i - 1))]);
}

int LCA(int nod1, int nod2) {
    int node1 = first[nod1], node2 = first[nod2];
    if (node1 > node2) swap(node1, node2);

    int put, dist = node2 - node1 + 1;

    for (put = 0; (1 << put) <= dist; ++put); --put;

    return min (rmq[put][node1], rmq[put][node2 - (1 << put) + 1]);
}

void make_dad(int nod) {
    used[nod] = 1;

    for (int i = 0; i < graph[nod].size(); ++i) {
        int node = graph[nod][i].first;

        if (!used[node]) {
            dad[node] = nod;
            cost[node] = graph[nod][i].second;
            make_dad(node);
        }
    }
}

void doSTRAMOSI() {
    for (int i = 1; i <= N; ++i)
        stramosi[0][i] = dad[i];

    for (int i = 1; (1 << i) <= N; ++i)
        for (int j = 1; j <= N; ++j)
            stramosi[i][j] = stramosi[i - 1][stramosi[i - 1][j]];

    for (int i = 1; i <= N; ++i)
        strmin[0][i] = cost[i];

    for (int i = 1; (1 << i) <= N; ++i)
        for (int j = 1; j <= N; ++j)
            strmin[i][j] = max (strmin[i - 1][j], strmin[i - 1][stramosi[i - 1][j]]);
}

int getMIN (int nod1, int nod2) {
    int maxim = -1;

    int dist = adan[nod1] - adan[nod2];
    int distMerge, nod = nod1;

    for (distMerge = 0; (1 << distMerge) <= dist; ++distMerge); --distMerge;

    while (dist != 0) {
        maxim = max (maxim, strmin[distMerge][nod]);
        nod = stramosi[distMerge][nod];
        dist -= (1 << distMerge);
        while ((1 << distMerge) > dist) --distMerge;
    }

    return maxim;
}

int main() {
    fin >> N >> M >> K;

    for (int i = 1; i <= M; ++i) {
        int x, y, c;
        fin >> x >> y >> c;
        muchie.push_back(make_muchia(x, y, c));
    }

    sort (muchie.begin(), muchie.end(), cmp);
    initPADURE();

    for (int i = 0; i < muchie.size(); ++i) {
        muchia a = muchie[i];
        if (getRADACINA(a.x) != getRADACINA(a.y)) {
            uneste(a.x, a.y);
            graph[a.x].push_back(make_pair(a.y, a.c));
            graph[a.y].push_back(make_pair(a.x, a.c));
        }
    }

    doDFS(1, 0);
    doRMQ();
    memset(used, 0, sizeof(used));
    make_dad(1);
    doSTRAMOSI();

    for (int i = 1; i <= K; ++i) {
        int nod1, nod2;
        fin >> nod1 >> nod2;

        int lca = LCA(nod1, nod2);

        fout << max (getMIN(nod1, lca), getMIN(nod2, lca)) << "\n";
    }

    return 0;
}