Cod sursa(job #2928003)

Utilizator BlueLuca888Girbovan Robert Luca BlueLuca888 Data 21 octombrie 2022 23:13:36
Problema Radiatie Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.24 kb
#include <bits/stdc++.h>

using namespace std;

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

const int MAX_M = 30005;
const int MAX_N = 15005;
int n, m, q, qu, qv;

struct EDGE{
    int u, v, c;
    inline bool operator < (const EDGE &rhs) const{
        return c < rhs.c;
    }
} input;

struct APM{
    public: vector <EDGE> edge;
    private: int tata[MAX_N], cost[MAX_N];

    private: int rnod;
    private: inline int root(const int &nod){
        rnod = nod;
        while(tata[rnod] != 0)
            rnod = tata[rnod];
        return rnod;
    }

    private: inline void redirect(int nod, int parent){
        if(tata[nod] != 0)
            redirect(tata[nod], nod);
        tata[nod] = parent;
        cost[nod] = cost[parent];
    }

    private: int ru, rv;
    private: inline void join(EDGE my_edge){
        ru = root(my_edge.u);
        rv = root(my_edge.v);
        if(ru != rv){
            /// dau redirect drumului dintre ru si my_edge.u
            redirect(my_edge.u, 0);
            /// dau redirect drumului dintre rv si my_edge.v
            redirect(my_edge.v, 0);

            tata[my_edge.u] = my_edge.v;
            cost[my_edge.u] = my_edge.c;
        }
    }

    private: int lvl[MAX_N];
    private: inline void set_lvl(int crt, int level){
        lvl[crt] = level;
        for(auto nxt : fii[crt])
            set_lvl(nxt, level+1);
    }

    private: int radacina;
    private: int ancestor[14][MAX_N], maximum[14][MAX_N], pw2[14], lg2[MAX_N];
    private: vector <int> fii[MAX_N];
    public: inline void build(){
        sort(edge.begin(), edge.end());

        for(auto muchie : edge)
            join(muchie);

        lg2[0] = lg2[1] = 0;
        for(int i=2; i<=n; i++)
            lg2[i] = lg2[i / 2] + 1;

        pw2[0] = 1;
        for(int i=1; i<=lg2[n]; i++)
            pw2[i] = (pw2[i-1] << 1);

        for(int j=1; j<=n; j++){
            ancestor[0][j] = tata[j];
            maximum[0][j] = cost[j];
        }

        for(int i=1; i<=lg2[n]; i++){
            for(int j=1; j<=n; j++){
                ancestor[i][j] = ancestor[i-1][ancestor[i-1][j]];
                maximum[i][j] = max(maximum[i-1][j], maximum[i-1][ancestor[i-1][j]]);
            }
        }

        for(int i=1; i<=n; i++){
            if(tata[i] == 0)
                radacina = i;
            else
                fii[tata[i]].push_back(i);
        }
        set_lvl(radacina, 1);
    }

    private: inline int stramos(int nod, int dist){
        int pw2 = 0;
        while(dist != 0){
            if(dist & 1)
                nod = ancestor[pw2][nod];
            pw2++;
            dist >>= 1;
        }
        return nod;
    }

    private: int st, md, dr, save, snod1, snod2;
    private: inline int lca(int nod1, int nod2){
        if(lvl[nod1] < lvl[nod2])
            swap(nod1, nod2);

        nod1 = stramos(nod1, lvl[nod1] - lvl[nod2]);

        st = 0;
        save = dr = lvl[nod1]-1;
        while(st <= dr){
            md = (st + dr) / 2;
            snod1 = stramos(nod1, md);
            snod2 = stramos(nod2, md);
            if(snod1 == snod2){
                save = md;
                dr = md - 1;
            }else
                st = md + 1;
        }
        return stramos(nod1, save);
    }

    private: inline int get_max(int nod, int parent){
        int answer = 0, pw2 = 0, dist = lvl[nod] - lvl[parent];
        while(dist != 0){
            if(dist & 1){
                answer = max(answer, maximum[pw2][nod]);
                nod = ancestor[pw2][nod];
            }
            pw2++;
            dist >>= 1;
        }
        return answer;
    }

    private: int lcaUV;
    public: inline int query(const int &u, const int &v){
        lcaUV = lca(u, v);
        return max(get_max(u, lcaUV), get_max(v, lcaUV));
    }

} tree;

int main (){
    ios_base::sync_with_stdio(false);
    fin.tie(nullptr), fout.tie(nullptr);

    fin>>n>>m>>q;
    for(int i=1; i<=m; i++){
        fin>>input.u>>input.v>>input.c;
        tree.edge.push_back(input);
    }

    tree.build();

    while(q--){
        fin>>qu>>qv;
        fout<<tree.query(qu, qv)<<"\n";
    }
    return 0;
}
/**

**/