Cod sursa(job #676010)

Utilizator elfusFlorin Chirica elfus Data 8 februarie 2012 16:21:03
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.87 kb
#include <stdio.h>
#include <vector>
#include <algorithm>
#define MMAX 30100
#define NMAX 15100

using namespace std;

struct muchie
{
    int x, y, cost;
} edge[MMAX];

struct par
{
    int son, cost;
};

vector <par> A[NMAX];
int n, T[NMAX], R[NMAX], Lev[2 * NMAX], First[NMAX], E[2 * NMAX], RM[15][2 * NMAX], Lg[2 * NMAX], LevNode[NMAX];
int x[15][NMAX], best[15][NMAX];
bool used[NMAX];

inline par makePar (int X, int Y)
{
    par aux;

    aux.son = X;
    aux.cost = Y;

    return aux;
}

inline bool comp (muchie A, muchie B)
{
    return A.cost < B.cost;
}

int getFather (int x)
{
    int root = x, aux;
    while (root != T[root])
        root = T[root];
    while (x != root)
    {
        aux = T[x];
        T[x] = root;
        x = aux;
    }

    return root;
}

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

void getAPM (int N, int M)
{
    int i, x, y;

    sort (edge + 1, edge + M + 1, comp);
    for (i = 1; i <= N; i ++)
        T[i] = i, R[i] = 1;

    for (i = 1; i <= M; i ++)
    {
        x = getFather (edge[i].x);
        y = getFather (edge[i].y);
        if (x == y)
            continue;
        A[edge[i].x].push_back (makePar (edge[i].y, edge[i].cost));
        A[edge[i].y].push_back (makePar (edge[i].x, edge[i].cost));
        unite (x, y);
    }
}

void DF (int X, int L)
{
    vector <par> :: iterator it;
    par now;

    used[X] = 1;
    E[++ n] = X;
    Lev[n] = L;
    LevNode[X] = L;
    First[X] = n;

    for (it = A[X].begin (); it != A[X].end (); it ++)
    {
        now = *it;
        if (used[now.son])
            continue;
        DF (now.son, L + 1);
        E[++ n] = X;
        Lev[n] = L;
        x[0][now.son] = X;
        best[0][now.son] = now.cost;
    }
}

void PreprocessLogs (int N)
{
    int i;

    Lg[1] = 0;
    for (i = 2; i <= N; i ++)
        Lg[i] = Lg[i >> 1] + 1;
}

void getLCA (int N)
{
    int i, j, step;

    DF (1, 1);

    //RMQ
    for (i = 1; i <= n; i ++)
        RM[0][i] = i;
    for (i = 1; (1 << i) <= n; i ++)
    {
        step = 1 << i;
        for (j = 1; j <= n; j ++)
        {
            if (j + step - 1 > N)
                break;
            if (Lev[RM[i - 1][j]] < Lev[RM[i - 1][j + (1 << (i - 1))]])
                RM[i][j] = RM[i - 1][j];
            else
                RM[i][j] = RM[i - 1][j + (1 << (i - 1))];
        }
    }
    PreprocessLogs (n);
}

int LCA (int X, int Y)
{
    X = First[X]; Y = First[Y];
    int le = Lg[Y - X + 1];

    if (Lev[RM[le][X]] < Lev[RM[le][Y - (1 << le) + 1]])
        return E[RM[le][X]];
    else
        return E[RM[le][Y - (1 << le) + 1]];
}

void Dinamica (int N) //bag ideea de la prob stramosi
{
    int i, j, lastNode;

    for (i = 1; (1 << i) <= N; i ++)
        for (j = 1; j <= N; j ++)
        {
            lastNode = x[i - 1][j];
            x[i][j] = x[i - 1][lastNode];
            best[i][j] = max (best[i - 1][j], best[i - 1][lastNode]);
        }
}

int Solve (int X, int Y)
{
    int step = LevNode[X] - LevNode[Y], sol = -1, i;

    for (i = 0; (1 << i) <= step; i ++)
        if (step & (1 << i))
        {
            sol = max (sol, best[i][X]);
            X = x[i][X];
        }

    return sol;
}

int main ()
{
    int i, N, M, Q, X, Y, lc;

    freopen ("radiatie.in", "r", stdin);
    freopen ("radiatie.out", "w", stdout);

    scanf ("%d%d%d", &N, &M, &Q);
    for (i = 1; i <= M; i ++)
        scanf ("%d%d%d", &edge[i].x, &edge[i].y, &edge[i].cost);

    getAPM (N, M);
    getLCA (N);
    Dinamica (N);

    while (Q --)
    {
        scanf ("%d%d", &X, &Y);
        lc = LCA (X, Y);
        printf ("%d\n", max (Solve (X, lc), Solve (Y, lc)));
    }

    return 0;
}