Cod sursa(job #1523246)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 12 noiembrie 2015 15:16:56
Problema Radiatie Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.43 kb
#include <cstdio>
#include <algorithm>

using std::swap;
using std::max;

const int MAX_N = 15000;
const int MAX_M = 30000;
const int LOG = 14;
const int NIL = -1;

/* pentru APM */
struct Edge {
    int u, v,
    cost;
};

Edge edges[MAX_M];

/* pentru DSU */
int father[MAX_N + 1];
int height[MAX_N + 1];

struct cell {
    int v, cost;
    int next;
};

cell l[2 * MAX_N];
int adj[MAX_N + 1];
int ptr;

int d[LOG][MAX_N + 1];
int c[LOG][MAX_N + 1];
int depth[MAX_N + 1];

__inline__ int log2(int X) {
    return 31 - __builtin_clz(X);
}

void dfs(int u, int pr) {
    for (int i = adj[u]; i != NIL; i = l[i].next) {
        int v = l[i].v;
        if (v != pr) {
            depth[v] = depth[u] + 1;
            d[0][v] = u;
            c[0][v] = l[i].cost;
            dfs(v, u);
        }
    }
}

int main(void) {
    freopen("radiatie.in", "r", stdin);
    freopen("radiatie.out", "w", stdout);
    int n, m, q;
    int u, v;

    scanf("%d%d%d", &n, &m, &q);

    for (int i = 0; i < m; i++) {
        scanf("%d%d%d", &edges[i].u, &edges[i].v, &edges[i].cost);
    }

    /* kruskal */
    std::sort(edges, edges + m, [] (const Edge &A, const Edge &B) {
        return A.cost < B.cost;
    });
    for (int i = 1; i <= n; i++) {
        adj[i] = NIL;
        father[i] = i;
        height[i] = 1;
    }

    for (int i = 0; i < m; i++) {
        auto getFather = [] (int x) -> int {
            int r = x;
            while (father[r] != r) {
                r = father[r];
            }
            while (father[x] != x) {
                int y = father[x];
                father[x] = r;
                x = y;
            }
            return r;
        };
        u = getFather(edges[i].u);
        v = getFather(edges[i].v);
        if (u != v) {
            auto unionSet = [] (int U, int V) -> void {
                if (height[V] > height[U]) {
                    swap(U, V);
                }
                father[V] = U;
                height[U] += (height[U] == height[V]);
            };
            auto addEdge = [&] (int U, int V, int C) -> void {
                l[ptr] = { V, C, adj[U] };
                adj[U] = ptr++;
            };
            unionSet(u, v);
            addEdge(edges[i].u, edges[i].v, edges[i].cost);
            addEdge(edges[i].v, edges[i].u, edges[i].cost);
        }
    }

    depth[1] = 1;
    dfs(1, 0);

    for (int i = 1; (1 << i) <= n; i++) {
        for (int j = 1; j <= n; j++) {
            d[i][j] = d[i - 1][ d[i - 1][j] ];
            c[i][j] = max(c[i - 1][j], c[i - 1][ d[i - 1][j] ]);
        }
    }

    while (q--) {
        scanf("%d%d", &u, &v);
        if (depth[u] > depth[v]) {
            swap(u, v);
        }
        int cost = 0;
        for (int k = log2(depth[v]); k >= 0; k--) {
            if (depth[v] - (1 << k) >= depth[u]) {
                cost = max(cost, c[k][v]);
                v = d[k][v];
            }
        }
        if (u != v) {
            for (int k = log2(depth[u]); k >= 0; k--) {
                if (d[k][u] && d[k][u] != d[k][v]) {
                    cost = max(cost, max(c[k][u], c[k][v]));
                    u = d[k][u];
                    v = d[k][v];
                }
            }
            cost = max(cost, c[0][u]);
            u = d[0][u];
        }
        printf("%d\n", cost);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}