Cod sursa(job #2348296)

Utilizator CronosClausCarare Claudiu CronosClaus Data 19 februarie 2019 16:28:01
Problema Radiatie Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.27 kb
#include <bits/stdc++.h>
#define ll long long
#define pp pair< int, int >
#define tt tuple< int, int, int >

using namespace std;

const int mxn = 15 * 1000 + 10;
const int mxx = 2e9;

vector< pp > graf[ mxn ];
vector< int > partial[ mxn ];
ll dist[ mxn ];

int nivel[ 2 * mxn ];
int parcurgere[ mxn ];
int poz[ mxn ];
int p;
int arb[ 8 * mxn ], arb_daddy[ 8 * mxn ];

int n, m, k;

int a, b;
int dad;

inline tt atribuire(pp muchie, int daddy){
    return make_tuple(muchie.first, muchie.second, daddy);
}

void construire_partial(){
    priority_queue< tt, vector< tt >, greater< tt > > q_min;
    bitset< mxn > viz;
    int ramas = n - 1;
    for(auto it: graf[ 1 ])
        q_min.push( atribuire( it, 1 ) );
    viz[ 1 ] = 1;
    int cost, nod, daddy;
    while(!q_min.empty() && ramas > 0){
        tie(cost, nod, daddy) = q_min.top();
        q_min.pop();
        if(viz[ nod ] == 0){
            partial[ daddy ].push_back( nod );
            ramas--;
            viz[ nod ] = 1;
            dist[ nod ] = cost;
            for(auto it: graf[ nod ])
                q_min.push( atribuire( it, nod ) );
        }
    }
}

void euler(int nod, int lvl){
    nivel[ nod ] = lvl;
    poz[ nod ] = p;
    parcurgere[ p++ ] = nod;
    for(auto it: partial[ nod ]){
        euler( it, lvl + 1 );
        parcurgere[ p++ ] = nod;
    }
}

void construire_minim(int nod, int st, int sf){
    if(st == sf){
        arb[ nod ] = parcurgere[ st ];
    }
    else{
        int mid = (st + sf) / 2;
        int p1 = 2 * nod;
        int p2 = 2 * nod + 1;
        construire_minim(p1, st, mid);
        construire_minim(p2, mid + 1, sf);
        if(dist[ arb[ p1 ] ] >= dist[ arb[ p2 ] ])
            arb[ nod ] = arb[ p1 ];
        else
            arb[ nod ] = arb[ p2 ];
    }
}

void construire_daddy(int nod, int st, int sf){
    if(st == sf){
        arb_daddy[ nod ] = parcurgere[ st ];
    }
    else{
        int mid = (st + sf) / 2;
        int p1 = 2 * nod;
        int p2 = 2 * nod + 1;
        construire_daddy(p1, st, mid);
        construire_daddy(p2, mid + 1, sf);
        if(nivel[ arb[ p1 ] ] <= nivel[ arb[ p2 ] ])
            arb_daddy[ nod ] = arb_daddy[ p1 ];
        else
            arb_daddy[ nod ] = arb_daddy[ p2 ];
    }
    //cout<< st << ' ' << sf << ' ' << arb_daddy[ nod ] << '\n';
}

int query(int nod, int st, int sf){
    if(st >= a && sf <= b){
        //cout<< st << ' ' << sf << ' ' << arb_daddy[ nod ] << '\n';
        return arb_daddy[ nod ];
    }
    else{
        if(!(st > b || sf < a)){
            int mid = (st + sf) / 2;
            int d1 = query(2 * nod, st, mid);
            int d2 = query(2 * nod + 1, mid + 1, sf);
            if(nivel[ d1 ] < nivel[ d2 ])
                return d1;
            else
                return d2;
        }
    }
    return 0;
}

int query_f(int nod, int st, int sf){
    if(st >= a && sf <= b){
        //cout<< st << ' ' << sf << ' ' << arb_daddy[ nod ] << '\n';
        if(arb[ nod ] != dad)
            return arb[ nod ];
    }
    else{
        if(!(st > b || sf < a)){
            int mid = (st + sf) / 2;
            int d1 = query_f(2 * nod, st, mid);
            int d2 = query_f(2 * nod + 1, mid + 1, sf);
            if(dist[ d1 ] >= dist[ d2 ])
                return d1;
            else
                return d2;
        }
    }
    return 0;
}

int main()
{
    ifstream cin("radiatie.in");
    ofstream cout("radiatie.out");
    cin>> n >> m >> k;
    for(int i = 1, x, y, z; i <= m; i++){
        cin>> x >> y >> z;
        graf[ x ].push_back(make_pair(z, y));
        graf[ y ].push_back(make_pair(z, x));
    }
    construire_partial();
    euler(1, 1);
    construire_minim(1, 0, p - 1);
    construire_daddy(1, 0, p - 1);
    for(int i = 1, x, y; i <= k; i++){
        cin>> x >> y;
        a = poz[ x ];
        b = poz[ y ];
        if(b < a)
            swap(a, b);
        nivel[ 0 ] = mxx;
        int daddy = query(1, 0, p - 1);
        dad = daddy;
        nivel[ 0 ] = 0;
        a = poz[ daddy ] + 1;
        b = poz[ x ];
        int d1 = dist[ query_f(1, 0, p - 1) ];
        b = poz[ y ];
        int d2 = dist[ query_f(1, 0, p - 1) ];
        cout<< max(d1, d2) << '\n';
    }

    return 0;
}