Cod sursa(job #1161019)

Utilizator gabrielinelusGabriel-Robert Inelus gabrielinelus Data 30 martie 2014 22:53:09
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.53 kb
#include <cstdio>
#include <queue>
#include <cmath>

#define Nmax 35005

using namespace std;
priority_queue<pair<int,pair<int,int> >,
        vector<pair<int,pair<int,int> > >,
       greater<pair<int,pair<int,int> > > > Q;
int N,M,K,nre;
vector<pair<int,int> > G[Nmax];
int daddy[Nmax];
int nivel[Nmax]; /// nivel[i] -> nivelul nodului i;
int ap[Nmax];
pair<int,int> euler[156][Nmax];;
int DP[16][Nmax];
int anc[16][Nmax];

void read()
{
    scanf("%d%d%d",&N,&M,&K);
    int a,b,c;
    for(int i = 1; i <= M; ++i)
    {
        scanf("%d%d%d",&a,&b,&c);
        Q.push(make_pair(c,make_pair(a,b)));
    }
    for(int i = 1; i <= N; ++i)daddy[i]=i;
}

int whos_ur_daddy(int k)
{
    if(daddy[k] != k)
        daddy[k] = whos_ur_daddy(daddy[k]);
    return daddy[k];
}

void couple(int a,int b)
{
    daddy[daddy[a]] = daddy[b];
}

void kruskal()
{
    int a,b,c;
    while(!Q.empty())
    {
        c = Q.top().first;
        a = Q.top().second.first;
        b = Q.top().second.second;
        Q.pop();
        if(whos_ur_daddy(a) != whos_ur_daddy(b))
        {
            couple(a,b);
            G[a].push_back(make_pair(c,b));
            G[b].push_back(make_pair(c,a));
        }
    }
}

void liniar(int k,int niv)
{
    nivel[k] = niv;
    euler[0][++nre].first = nivel[k];
    euler[0][nre].second = k;
    for(vector<pair<int,int> >::iterator it = G[k].begin(); it != G[k].end(); ++it)
        if(!nivel[it->second])
        {
            DP[0][it->second] = it->first;
            anc[0][it->second] = k;
            liniar(it->second,niv+1);
            euler[0][++nre].first = nivel[k];
            euler[0][nre].second = k;
        }
}

void LCA()
{
    for(int i = 1; i <= nre; ++i)if(!ap[euler[0][i].second]) ap[euler[0][i].second] = i;
    int IT = 1,lg = (int)log2(nre);
    for(int i = 1; i <= lg; ++i)
    {
        for(int j = 1; j <= nre; ++j)
            if(j + IT <= nre) euler[i][j] = min(euler[i-1][j],euler[i-1][j+IT]);
            else euler[i][j] = euler[i][j-1];
        IT <<= 1;
    }
}
int Querry(int a,int b) /// returns the LCA of a and b
{
    a = ap[a];
    b = ap[b];
    if(a>b) swap(a,b);
    int lg =(int)log2(b-a+1);
    if(euler[lg][a] < euler[lg][b-(1<<lg)+1]) return euler[lg][a].second;
    return euler[lg][b-(1<<lg)+1].second;
}

void precalc()
{
    int lg = (int)log2(N);
    for(int i = 1; i <= lg; ++i)
        for(int j = 1; j <= N; ++j)
        {
            anc[i][j] = anc[i-1][anc[i-1][j]]; /// anc[i][j] -> 2^i th ancestor of j
            DP[i][j] = max(DP[i-1][j],DP[i-1][anc[i-1][j]]); /// DP[i][j] -> max cost of travel to 2^i th ancestor of j
        }
}

int get_min(int x,int y)
{
    y = nivel[x] - nivel[y]; ///  la al catalea stramos vreau sa ajung
    if( y == 0 ) return 0; /// dak nu ma duc nicaieri
    int rez = 0;
    while(y)
    {
        for(int i = 0; i <= 14; ++i)
            if(y && (y & ( 1 << i )))
            {
                y -= (1<<i);
                rez = max(rez,DP[i][x]);
                x = anc[i][x];
            }
    }
    return rez;
}

void answer()
{
    int a,b,lc,ix,iy;
    for(int i = 1; i <= K; ++i)
    {
        scanf("%d%d",&a,&b);
        lc = Querry(a,b);
        ix = get_min(a,lc);
        iy = get_min(b,lc);
        printf("%d\n",max(ix,iy));
    }
}

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

    read();
    kruskal();
    liniar(1,1);
    LCA();
    precalc();
    answer();

    return 0;
}