Cod sursa(job #2193326)

Utilizator DawlauAndrei Blahovici Dawlau Data 9 aprilie 2018 19:13:21
Problema Radiatie Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.34 kb
#include<fstream>
#include<algorithm>
#include<list>
#include<deque>
using namespace std;

const int MaxNodesCnt = 15e3 + 5, MaxEdgesCnt = 3e4 + 5, buffSZ = 4e4;

char readBuff[buffSZ];
int readBuffP = buffSZ - 1;

inline void read(int &no){

    while(!isdigit(readBuff[readBuffP]))
        if(++readBuffP == buffSZ){

            readBuffP = 0;
            fread(readBuff, 1, buffSZ, stdin);
        }
    no = 0;
    while(isdigit(readBuff[readBuffP])){
        no = no * 10 + readBuff[readBuffP] - '0';
        if(++readBuffP == buffSZ){

            readBuffP = 0;
            fread(readBuff, 1, buffSZ, stdin);
        }
    }
}

struct edge{

    int node1, node2, cost;
};

edge edges[MaxEdgesCnt];
int Father[MaxNodesCnt], Rank[MaxNodesCnt], level[MaxNodesCnt], edgeCost[MaxNodesCnt];
int nodesCnt, edgesCnt, K, root;

list<int> adjList[MaxNodesCnt];

inline void readData(){

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

    read(nodesCnt); read(edgesCnt); read(K);

    int from, to, cost, idx;
    for(idx = 1; idx <= edgesCnt; ++idx){

        read(from); read(to); read(cost);
        edges[idx] = {from, to, cost};

        Father[from] = from; Father[to] = to;  ///union-find stuff
        Rank[from] = 1; Rank[to] = 1;
    }
}

inline bool compCrit(const edge &edge1, const edge &edge2){

    return edge1.cost < edge2.cost;
}

inline int Root(int node){

    int root;
    for(root = node; Father[root] != root; root = Father[root]);
    return root;
}

inline void Unite(int root1, int root2, int cost){

    if(Rank[root1] > Rank[root2]){

        Father[root2] = root1;
        edgeCost[root2] = cost;
        adjList[root1].push_back(root2); ///building tree
    }
    else{

        Father[root1] = root2;
        edgeCost[root1] = cost;
        adjList[root2].push_back(root1);
    }
    if(Rank[root1] == Rank[root2])
        ++Rank[root2];
}

inline void findAPM(){

    int idx, node1, node2, root1, root2, cost;
    for(idx = 1; idx <= edgesCnt; ++idx){

        node1 = edges[idx].node1;
        node2 = edges[idx].node2;
        cost = edges[idx].cost;

        root1 = Root(node1);
        root2 = Root(node2);

        if(root1 != root2)
            Unite(root1, root2, cost);
    }
}

inline void BFS(int node){

    deque<int> Queue;
    level[node] = 1;
    Queue.push_back(node);

    while(!Queue.empty()){

        node = Queue.front();
        Queue.pop_front();

        for(const int &nextNode : adjList[node]){

            level[nextNode] = level[node] + 1;
            Queue.push_back(nextNode);
        }
    }
}

inline int LCA(int node1, int node2){

    int maxEdge = 0;

    while(node1 != node2){

        if(level[node1] > level[node2]){

            maxEdge = max(maxEdge, edgeCost[node1]);
            node1 = Father[node1];
        }
        else{

            maxEdge = max(maxEdge, edgeCost[node2]);
            node2 = Father[node2];
        }
    }
    return maxEdge;
}

inline void solveQueries(){

    int node1, node2;

    while(K--){

        read(node1); read(node2);
        printf("%d\n", LCA(node1, node2));
    }
}

int main(){

    readData();
    sort(edges + 1, edges + 1 + edgesCnt, compCrit);
    findAPM();
    BFS(Root(1));
    solveQueries();
}