Cod sursa(job #2394501)

Utilizator refugiatBoni Daniel Stefan refugiat Data 1 aprilie 2019 17:51:52
Problema Radiatie Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.63 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream si("radiatie.in");
ofstream so("radiatie.out");

inline int max(int x, int y) {
    return x>y?x:y;
}

inline void swap(int& x, int& y) {
    int aux=x;
    x=y;
    y=aux;
}

int log2(int x) {
    for(int i=31; i>=0; i--)
        if(x&(1<<i))
            return i;
    return 0;
}
struct Edge {
    int x, y;
    int cost;
};
inline bool operator<(Edge x, Edge y) {
    return x.cost>y.cost;
}

class Forest {
  private:
    vector<int> height;
    vector<int> father;

  public:
    Forest(int n) {
        height.resize(n+1);
        father.resize(n+1);
    }

    int find(int x) {
        int root=x;
        while(father[root])
            root=father[root];

        int aux;
        while (father[x]) {
            aux=father[x];
            father[x]=root;
            x=aux;
        }
        return root;
    }

    void unite(int rootX, int rootY) {
        if(height[rootX]<height[rootY])
            father[rootX]=rootY;
        else {
            father[rootY]=rootX;
            if(height[rootX]==height[rootY])
                height[rootX]++;
        }
    }
};
class Tree {
    private:
    struct Node {
        int node, cost;
        Node(int node=0, int cost=0) {
            this->node=node;
            this->cost=cost;
        }
    };

    int n;
    vector<Node> father;
    vector<vector<Node>> ad;

    int height;
    vector<int> level;

    vector<vector<int>> anc;
    vector<vector<int>> len;

    int nthAnc(int node, int n) {
        if(n>level[node])
            return 0;

        int k=node;
        for(int i=31; i>=0; i--)
            if(n&(1<<i))
                k=anc[k][i];
        return k;
    }

    void dfs(int node, int dad) {
        for(Node nghb: ad[node])
            if(nghb.node!=dad) {
                level[nghb.node]=level[node]+1;
                height=max(height, level[nghb.node]);
                father[nghb.node]=Node(node, nghb.cost);
                dfs(nghb.node, node);
            }
    }
    public:
    Tree(int n) {
        this->n=n;
        ad.resize(n+1);
    }

    void addEdge(Edge edge) {
        ad[edge.x].push_back(Node(edge.y, edge.cost));
        ad[edge.y].push_back(Node(edge.x, edge.cost));
    }
    void dp() {
        father.resize(n + 1);
        level.resize(n + 1);
        height=0;
        dfs(1, 0);
        int log=log2(height);
        anc=vector<vector<int>>(n+1, vector<int>(log));
        len=vector<vector<int>>(n+1, vector<int>(log));
        for(int i=1; i<=n; i++) {
            anc[i][0]=father[i].node;
            len[i][0]=father[i].cost;
        }
        for(int j=1; j<=log; j++)
            for(int i=1; i<=n; i++) {
                anc[i][j]=anc[anc[i][j-1]][j-1];
                len[i][j]=max(len[i][j-1], len[anc[i][j-1]][j-1]);
            }
    }
    int query(int x, int y) {
        if(level[x]>level[y])
            swap(x, y);
        int sol=father[y].cost;
        if(level[y]>level[x]) {
            int z=level[y]-level[x];
            for(int i=31; i>=0; i--)
                if(z&(1<<i)) {
                    sol=max(sol, len[y][i]);
                    y=anc[y][i];
                }
        }
        if(x==y)
            return sol;
        int lo=0, hi=level[x]+1;
        while(hi-lo>1) {
            int md=(lo+hi)>>1;
            if(nthAnc(x, md)==nthAnc(y, md))
                hi=md;
            else
                lo=md;
        }
        for(int i=31; i>=0; i--)
            if(hi&(1<<i)) {
                sol=max(sol, len[x][i]);
                x=anc[x][i];
                sol=max(sol, len[y][i]);
                y=anc[y][i];
            }
        return sol;
    }
};

Tree kruskal(int n, vector<Edge>& edges) {
    Forest forest(n);
    make_heap(edges.begin(), edges.end());

    Tree mst(n);
    for(int i=1; i<n; ) {
        Edge edge=edges[0];
        pop_heap(edges.begin(), edges.end());
        edges.pop_back();

        int rootX=forest.find(edge.x);
        int rootY=forest.find(edge.y);

        if(rootX!=rootY) {
            i++;
            mst.addEdge(edge);
            forest.unite(rootX, rootY);
        }
    }
    return mst;
}
int main()
{
    int n, m, k;
    si>>n>>m>>k;
    vector<Edge> edges(m);
    for(int i=0; i<m; ++i) {
        si>>edges[i].x>>edges[i].y>>edges[i].cost;
    }
    Tree mst=kruskal(n, edges);
    mst.dp();
    for(int i=0; i<k; ++i) {
        int x, y;
        si>>x>>y;
        so<<mst.query(x, y)<<'\n';
    }
    return 0;
}