Cod sursa(job #1097018)

Utilizator Ionut228Ionut Calofir Ionut228 Data 2 februarie 2014 21:00:09
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.14 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

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

int N, M, nr_question;
int K, first_nod, log_N;
int X[30002], Y[30002], C[30002], pos[30002], C_stramos[15001];
int T[30002], R[30002];
int LVL[30002], EULER[30002], logaritm[30002], First[15001];
int RMQ[60001][20];
int stramos[20][15001], max_muchie[20][15001];
vector<pair<int, int> > V[15001];
bool used[15001], used_stramos[15001];

bool cmp(int a, int b)
{
    return (C[a] < C[b]);
}

int find(int x)
{
    int rad, aux;

    for (rad = x; T[rad] != rad; rad = T[rad]);

    while (T[rad] != rad)
    {
        aux = T[x];
        T[x] = rad;
        x = aux;
    }

    return rad;
}

void unite(int x, int y)
{
    if (R[x] > R[y]) T[y] = x;
    else             T[x] = y;

    if (R[x] == R[y]) ++R[y];
}

void apm()
{
    sort(pos + 1, pos + M + 1, cmp);
    for (int i = 1; i <= N; ++i)
    {
        T[i] = i;
        R[i] = 1;
    }

    for (int i = 1; i <= M; ++i)
    {
        int nr1 = find(X[pos[i]]);
        int nr2 = find(Y[pos[i]]);

        if (nr1 != nr2)
        {
            unite(nr1, nr2);

            if (!first_nod) first_nod = X[pos[i]];
            V[X[pos[i]]].push_back(make_pair(Y[pos[i]], C[pos[i]]));
            V[Y[pos[i]]].push_back(make_pair(X[pos[i]], C[pos[i]]));
        }
    }
}

void dfs(int nod, int nivel)
{
    used[nod] = true;

    EULER[++K] = nod; //nodul actual este adaugat in reprezentarea Euler a arborelui
    LVL[K] = nivel; //se retine nivelul fiecarei pozitii din reprezentarea Euler a arborelui
    First[nod] = K; //se retine prima aparitie a fiecarui nod in reprezentarea Euler

    for (vector<pair<int, int> >::iterator it = V[nod].begin(); it != V[nod].end(); ++it)
    {
        if (!used[it->first])
        {
            stramos[0][it->first] = nod;
            max_muchie[0][it->first] = it->second;

            dfs(it->first, nivel + 1);

            EULER[++K] = nod;
            LVL[K] = nivel;
        }
    }
}

void rmq()
{
    //in RMQ[i][j] va fi nodul de nivel minim dintre pozitiile (j, j + 2 ^ (i - 1)) din reprezentarea Euler a arborelui
    logaritm[1] = 0;
    for (int i = 2; i <= K; ++i)
        logaritm[i] = logaritm[i >> 1] + 1;
    for (int i = 1; i <= K; ++i)
        RMQ[i][0] = i;

    for (int j = 1; (1 << j) <= K; ++j)
        for (int i = 1; i + (1 << (j - 1)) <= K; ++i)
        {
            int p  = 1 << (j - 1);

            if (LVL[RMQ[i][j - 1]] <= LVL[RMQ[i + p][j - 1]]) RMQ[i][j] = RMQ[i][j - 1];
            else                                              RMQ[i][j] = RMQ[i + p][j - 1];
        }
}

int lca(int nod1, int nod2)
{
    //LCA-ul nodurilor nod1 si nod2 va fi nodul cu nivel minim din secventa (First[nod1], First[nod2]) din reprezentarea Euler
    int sol;
    int start = First[nod1];
    int finish = First[nod2];

    if (start > finish) swap(start, finish);
    int dif = finish - start + 1;
    int l = logaritm[dif];

    if (LVL[RMQ[start][l]] <= LVL[RMQ[finish - (1 << l) + 1][l]]) sol = RMQ[start][l];
    else                                                          sol = RMQ[finish - (1 << l) + 1][l];

    return EULER[sol];
}

void idee_stramosi()
{
    for (int k = 1; k <= log_N; ++k)
        for (int i = 1; i <= N; ++i)
        {
            stramos[k][i] = stramos[k - 1][stramos[k - 1][i]];

            if (max_muchie[k - 1][stramos[k - 1][i]] == 0) max_muchie[k][i] = 0;
            else                                           max_muchie[k][i] = max(max_muchie[k - 1][i], max_muchie[k - 1][stramos[k - 1][i]]);
        }
}

int find_stramos(int nod_c, int nod)
{
    int nod_stramos;
    bool ok = true;

    if (nod == 0)
    {
        nod_stramos = nod_c;
        ok = false;
    }

    while(ok)
    {
        if (nod == 0 || nod == 1)
        {
            ok = false;
            break;
        }

        int l = logaritm[nod];
        nod_stramos = stramos[l][nod_c];
        nod_c = stramos[l][nod_c];

        nod = nod - (1 << l);
    }
    if (nod == 1) nod_stramos = stramos[0][nod];

    return nod_stramos;
}

int main()
{
    fin >> N >> M >> nr_question;
    for (int i = 1; i <= M; ++i)
    {
        fin >> X[i] >> Y[i] >> C[i];
        pos[i] = i;
    }
    log_N = log2(N);

    apm();
    dfs(first_nod, 1);
    rmq();
    idee_stramosi();


    for (int i = 1, nod1, nod2; i <= nr_question; ++i)
    {
        int sol1, sol2, l, nr_stramos;
        fin >> nod1 >> nod2;

        int stramos = lca(nod1, nod2);

        l = logaritm[LVL[First[nod1]] - LVL[First[stramos]]];
        nr_stramos = find_stramos(nod1, LVL[First[nod1]] - 1 - l);

        sol1 = max(max_muchie[l][nod1], max_muchie[l][nr_stramos]);


        l = logaritm[LVL[First[nod2]] - LVL[First[stramos]]];
        nr_stramos = find_stramos(nod2, LVL[First[nod2]] - 1 - l);

        sol2 = max(max_muchie[l][nod2], max_muchie[l][nr_stramos]);


        fout << max(sol1, sol2) << '\n';
    }


    fin.close();
    fout.close();
    return 0;
}