Cod sursa(job #2558312)

Utilizator Rares31100Popa Rares Rares31100 Data 26 februarie 2020 14:38:37
Problema Radiatie Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.3 kb
#include <bits/stdc++.h>
#define TIII tuple<int,int,int>

using namespace std;

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

int n,m,q;
int vf[30001],urm[30001],cost[30001],last[15001],nr;

TIII muchie[30001];
int Union[15001],unSize[15001];

int eul[30001],nivel[30001],poz[15001],nrE;
bitset <15001> viz;
int rmq[16][30001];

int tata[15001],cdrum[15001];
int stram[15][15001],maxDrum[15][15001],Nivel[15001];

void adauga(int nod,int vec,int ct)
{
    vf[++nr]=vec;
    urm[nr]=last[nod];
    last[nod]=nr;
    cost[nr]=ct;
}

int rad(int nod)
{
    while(nod!=Union[nod])
        nod=Union[nod];

    return nod;
}

void uneste(int i,int j)
{
    int ri=rad(i);
    int rj=rad(j);

    if(unSize[ri]<unSize[rj])
        swap(ri,rj);

    Union[rj]=ri;
    unSize[ri]+=unSize[rj];
}

void Kruskal()
{
    sort(muchie+1,muchie+1+m);

    for(int ct,i,j,k=1;k<=m;k++)
    {
        tie(ct,i,j)=muchie[k];

        if(rad(i)!=rad(j))
        {
            uneste(i,j);
            adauga(i,j,ct);
            adauga(j,i,ct);
        }
    }
}

void Edfs(int nod,int from,int niv=1)
{
    tata[nod]=from;
    viz[nod]=1;
    eul[++nrE]=nod;
    nivel[nrE]=niv;
    poz[nod]=nrE;
    Nivel[nod]=niv;

    for(int k=last[nod];k;k=urm[k])
        if(!viz[ vf[k] ])
        {
            Edfs(vf[k],nod,niv+1);
            eul[++nrE]=nod;
            nivel[nrE]=niv;
        }
        else if(vf[k]==from)
            cdrum[nod]=cost[k];
}

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

    int rMax=log2(nrE);

    for(int r=1,l=1;r<=rMax;r++,l*=2)
        for(int i=1;i<=nrE-2*l+1;i++)
            if(nivel[ rmq[r-1][i] ]<nivel[ rmq[r-1][i+l] ])
                rmq[r][i]=rmq[r-1][i];
            else
                rmq[r][i]=rmq[r-1][i+l];
}

void distante()
{
    for(int i=1;i<=n;i++)
    {
        stram[0][i]=tata[i];
        maxDrum[0][i]=cdrum[i];
    }

    int rMax=log2(n);

    for(int r=1;r<=rMax;r++)
        for(int i=1;i<=n;i++)
        {
            stram[r][i]=stram[r-1][ stram[r-1][i] ];
            maxDrum[r][i]=max( maxDrum[r-1][i] , maxDrum[r-1][ stram[r-1][i] ] );
        }
}

int lca(int i,int j)
{
    if(poz[i]>poz[j])
        swap(i,j);

    int r=log2(poz[j]-poz[i]+1);
    int l=1<<r;
    int st=poz[i],dr=poz[j];

    int minim;

    if(nivel[ rmq[r][st] ]<nivel[ rmq[r][dr-l+1] ])
        minim=rmq[r][st];
    else
        minim=rmq[r][dr-l+1];

    return eul[minim];
}

int drumul(int i,int nod)
{
    int maxim=0;
    int r=log2( Nivel[i]-Nivel[nod] );

    for(;r>=-1;r--)
        while(Nivel[ stram[r][i] ]>=Nivel[nod])
        {
            maxim=max(maxim, maxDrum[r][i]);
            i=stram[r][i];
        }

    return maxim;
}

int main()
{
    in>>n>>m>>q;

    for(int i,j,ct,k=1;k<=m;k++)
    {
        in>>i>>j>>ct;
        muchie[k]=make_tuple(ct,i,j);
    }

    for(int i=1;i<=n;i++)
    {
        Union[i]=i;
        unSize[i]=1;
    }

    Kruskal();

    for(int i=1;i<=n;i++)
        if(!viz[i])
            Edfs(i,0);

    RMQ();
    distante();

    for(int i,j,k=1;k<=q;k++)
    {
        in>>i>>j;
        int nod=lca(i,j);

        out<<max( drumul(i,nod) , drumul(j,nod) )<<'\n';
    }

    return 0;
}