Cod sursa(job #1010363)

Utilizator romircea2010FMI Trifan Mircea Mihai romircea2010 Data 14 octombrie 2013 19:28:18
Problema Radiatie Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.74 kb
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <ctime>
#define lim 1000000
#define Next ++pos == lim?f.read(buffer, lim), pos = 0:0
#define NMax 15010
#define MMax 30010

using namespace std;

ifstream f ("radiatie.in");
struct NOD
{
    int x, cost;
    NOD (const int _x, const int _cost)
    {
        x = _x;
        cost = _cost;
    }
    NOD()
    {
        x = cost = 0;
    }
};
vector <NOD> G[NMax];
struct stramos
{
    int ancestor, cost;
    stramos(const int _ancestor, const int _cost)
    {
        ancestor = _ancestor;
        cost = _cost;
    }
    stramos()
    {
        ancestor = cost = 0;
    }
};
stramos mat[14][NMax];

int euler[2*NMax+1], height_euler[2*NMax+1], rmq[15][2*NMax+1], lg[2*NMax+1], first_euler[NMax], pas;
int level[NMax], father[NMax], cost_to_father[NMax], maxim;
bool viz[NMax], viz_euler[NMax];
int comp[NMax];
int n, m, K;
int pos, nvedges;
char buffer[lim];
struct muchie
{
    int x, y, cost;
    muchie (const int _x, const int _y, const int _cost)
    {
        x = _x;
        y = _y;
        cost = _cost;
    }
    muchie()
    {
        x = y = cost = 0;
    }
    bool operator <(const muchie &A) const
    {
        return cost < A.cost;
    }
};
muchie vedges[MMax];

inline void Read(int &x)
{
    for (; buffer[pos] < '0' || buffer[pos] > '9'; Next);
    for (x = 0; '0' <= buffer[pos] && buffer[pos] <= '9'; x = x*10 + buffer[pos] - '0', Next);
}

void Init()
{
    int i;
    for (i=1; i<=n; ++i)
        comp[i] = i;
}

inline int find(int x)
{
    int r = x, y;
    while (comp[r] != r)
        r = comp[r];
    while (comp[x]!=r)
    {
        y = comp[x];
        comp[x] = r;
        x = y;
    }
    return r;
}

inline void unite (const int x, const int y)
{
    if (rand() & 1)
        comp[x] = y;
    else
        comp[y] = x;
}

void DoAPM()
{
    Init();
    int fx, fy, nrcomp = n, x, y, cost;
    for (int i = 1; i<=nvedges && nrcomp != 1; ++i)
    {
        fx = find(vedges[i].x), fy = find(vedges[i].y);
        if (fx != fy)
        {
            unite(fx, fy);
            x = vedges[i].x;
            y = vedges[i].y;
            cost = vedges[i].cost;
            --nrcomp;
            G[x].push_back(NOD(y, cost));
            G[y].push_back(NOD(x, cost));
        }
    }
}

void DFS(const int node, const int lvl)
{
    viz[node] = true;
    level[node] = lvl;
    NOD aux;
    for (vector <NOD>::iterator it = G[node].begin(); it!=G[node].end(); ++it)
    {
        aux = *it;
        if (!viz[aux.x])
        {
            father[aux.x] = node;
            cost_to_father[aux.x] = aux.cost;
            DFS(aux.x, lvl+1);
        }
    }
}

void CreateLG()
{
    int i, limit = 2*n+2;
    lg[1] = 0;
    for (i=2; i<=limit; ++i)
        lg[i] = 1 + lg[i>>1];
}

void DFS_euler (const int node, const int lvl)
{
    ++pas;
    viz_euler[node] = true;
    euler[pas] = node;
    height_euler[pas] = lvl;
    first_euler[node] = pas;
    NOD aux;
    for (vector <NOD>::iterator it = G[node].begin(); it!=G[node].end(); ++it)
    {
        aux = *it;
        if (!viz_euler[aux.x])
        {
            DFS_euler(aux.x, lvl+1);
            ++pas;
            euler[pas] = node;
            height_euler[pas] = lvl;
        }
    }
}

void CreateLCA()
{
    CreateLG();
    DFS_euler(1, 0);
    int i, j, limit;
    for (i=1; i<=pas; ++i)
        rmq[0][i] = i;
    for (i=1; (1<<i) <= pas; ++i)
    {
        limit = pas - (1<<i) + 1;
        for (j=1; j<=limit; ++j)
        {
            rmq[i][j] = rmq[i-1][j];
            if (height_euler[rmq[i][j]] > height_euler[rmq[i-1][j+(1<<(i-1))]])
                rmq[i][j] = rmq[i-1][j+(1<<(i-1))];
        }
    }
}

inline int GetLCA(int x, int y)
{
    x = first_euler[x];
    y = first_euler[y];
    if (x > y)
        swap(x, y);
    int dif, l, poz;
    dif = y - x + 1;
    l = lg[dif];
    poz = rmq[l][x];
    if (height_euler[poz] > height_euler[rmq[l][x + dif - (1<<l)]])
        poz = rmq[l][x + dif - (1<<l)];
    return euler[poz];
}

void CreateAncestors()
{
    DFS(1, 0);
    /// mat[i][j].ancestor = al 2^i-lea stramos al nodului j
    /// mat[i][j].cost = costul muchiei maxime de la nodul j pana la al 2^i-lea stramos al sau
    int i, j;
    for (i=1; i<=n; ++i)
    {
        mat[0][i].ancestor = father[i];
        mat[0][i].cost = cost_to_father[i];
    }
    for (i=1; (1<<i) <= n; ++i)
    {
        for (j = 1; j<=n; ++j)
        {
            mat[i][j].ancestor = mat[i-1][mat[i-1][j].ancestor].ancestor;
            mat[i][j].cost = max(mat[i-1][j].cost, mat[i-1][mat[i-1][j].ancestor].cost);
        }
    }
}

inline void GetAnc(int node, int nr)
{
    int l;
    while (nr > 0)
    {
        l = lg[nr];
        maxim = max(maxim, mat[l][node].cost);
        nr -= (1<<l);
        node = mat[l][node].ancestor;
    }
}

inline int Solve(int node, int lca)
{
    if (node == lca)
        return 0;
    int lvl;
    lvl = level[node] - level[lca];
    maxim = 0;
    GetAnc(node, lvl);
    return maxim;
}

void Solve()
{
    ofstream g("radiatie.out");
    srand(time(NULL));
    Read(n), Read(m), Read(K);
    int i, x, y, cost, lca, ans;
    for (i=1; i<=m; ++i)
    {
        Read(x), Read(y), Read(cost);
        vedges[++nvedges] = muchie (x, y, cost);
    }
    sort(vedges+1, vedges+nvedges+1);
    DoAPM();
    CreateLCA();
    CreateAncestors();
    for (i=1; i<=K; ++i)
    {
        Read(x), Read(y);
        lca = GetLCA(x, y);
        ans = max(Solve(x, lca), Solve(y, lca));
        g<<ans<<"\n";
    }
    f.close();
    g.close();
}

int main()
{
    Solve();
    return 0;
}