Cod sursa(job #1640650)

Utilizator cautionPopescu Teodor caution Data 8 martie 2016 18:46:28
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.59 kb
#include <fstream>
#include <vector>
#include <algorithm>

constexpr int kMaxN = 15000;
constexpr int kMaxRmqLevels = 17;
struct Edge
{
    int x, y, weight;
    Edge(int arg_x, int arg_y, int arg_weight) :
        x(arg_x), y(arg_y), weight(arg_weight)
    {
    }
    bool operator<(const Edge& edge) const
    {
        return weight < edge.weight;
    }
};
Edge makeEdge(int x, int y, int weight)
{
    Edge temp(x, y, weight);
    return temp;
}

int n, m, k;
std::vector<Edge> v_edges;
std::vector<std::pair<int, int> > mst[kMaxN];
std::vector<int> rmq[kMaxRmqLevels]; //contains the edge from the i-th to (i+1)-th euler positions
std::vector<int> euler_positions[kMaxN];

int queryRmq(int a, int b)
{
    int j = 0;
    int result = 0;
    while(a <= b) {
        if(a%2 == 1) {
            result = std::max(result, rmq[0][a]);
            ++a;
        }
        if(b >= a && b%2 == 0) {
            result = std::max(result, rmq[0][b]);
            --b;
        }
        if(b < a) break;
        a/=2; b/=2;
        ++j;
    }
    return result;
}
void buildRmq()
{
    int j = 0;
    while(true) {
        ++j;
        for(int i = 1; i*2 <= rmq[j-1].size(); ++i) {
            rmq[j].push_back(std::max(rmq[j-1][i*2-2], rmq[j-1][i*2-1]));
        }
        if(rmq[j].size() < 2) return;
    }
}

//Dfs for mst to compute euler positions and the rmq
void dfs(int x, int parent)
{
    euler_positions[x].push_back(rmq[0].size());
    for(auto& edge : mst[x]) {
        if(edge.first != parent) {
            rmq[0].push_back(edge.second);
            dfs(edge.first, x);
            rmq[0].push_back(edge.second);
            euler_positions[rmq[0].size()];
        }
    }
}
//Kruskal's algorithm
void computeMst()
{
    int *v = new int[n+1];
    std::sort(v_edges.begin(), v_edges.end());
    for(int i = 1; i <= n; ++i) v[i] = 0;
    for(auto& edge : v_edges) {
        int x = edge.x;
        int y = edge.y;
        int a = x, b = y;
        while(v[a] != 0) a = v[a];
        while(v[b] != 0) b = v[b];
        if(a != b) {
            mst[x].push_back(std::make_pair(y, edge.weight));
            mst[y].push_back(std::make_pair(x, edge.weight));
            v[a] = b;
        }
        int aux;
        while(x != a) {
            aux = v[x];
            v[x] = a;
            x = aux;
        }
        while(y != b) {
            aux = v[y];
            v[y] = b;
            y = aux;
        }
    }
}
int query(int x, int y)
{
    if(euler_positions[x].back() < euler_positions[y].front())
        return queryRmq(euler_positions[x].back(), euler_positions[y].front());
    else if(euler_positions[y].back() < euler_positions[x].front())
        return queryRmq(euler_positions[y].back(), euler_positions[x].front());
    else {
        if(euler_positions[x].front() < euler_positions[y].front()) {
            for(auto it = euler_positions[x].begin(); it != euler_positions[x].end(); ++it) {
                if(*it > euler_positions[y].front()) return queryRmq(*(it-1), euler_positions[y].front());
            }
        }
        else {
            for(auto it = euler_positions[y].begin(); it != euler_positions[y].end(); ++it) {
                if(*it > euler_positions[y].front()) return queryRmq(*(it-1), euler_positions[x].front());
            }
        }
    }
    return 0;
}
int main()
{
    std::ifstream in("radiatie.in");
    std::ofstream out("radiatie.out");
    in>>n>>m>>k;
    for(int x, y, w, i = 1; i <= m; ++i) {
        in>>x>>y>>w;
        v_edges.push_back(makeEdge(x, y, w));
    }
    computeMst();
    dfs(1, 0);
    buildRmq();
    for(int x, y, i = 1; i <= k; ++i) {
        in>>x>>y;
        out<<query(x, y)<<'\n';
    }
}