Cod sursa(job #1523330)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 12 noiembrie 2015 16:59:52
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.36 kb
#include <cstdio>
#include <algorithm>

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

const int MAX_N = 15000;
const int MAX_M = 30000;
const int SQRTN = 123;
const int NIL = -1;

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

Edge edges[MAX_M];

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

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

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

int parent[MAX_N];
int group[MAX_N];
int depth[MAX_N];

int costBucket[MAX_N];
int bucket;
int tcost[MAX_N];

void DFS(int u, int d, int gr) {
    depth[u] = d;
    group[u] = gr;

    if (!(depth[u] % bucket)) {
        gr = u;
    }
    for (int i = adj[u]; i != NIL; i = l[i].next) {
        if (parent[l[i].v] == NIL) {
            costBucket[gr] = max(costBucket[gr], l[i].cost);
            parent[l[i].v] = u;
            tcost[l[i].v] = l[i].cost;
            DFS(l[i].v, d + 1, gr);
        }
    }
}


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);
        edges[i].u--;
        edges[i].v--;
    }

    /* kruskal */
    std::sort(edges, edges + m, [] (const Edge &A, const Edge &B) {
        return A.cost < B.cost;
    });
    for (int i = 0; i < n; i++) {
        parent[i] = NIL;
        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);
        }
    }

    bucket = (int) sqrt(n - 1) + 1;
    DFS(0, 1, 0);

    while (q--) {
        scanf("%d%d", &u, &v);
        u--;
        v--;
        int cost = 0;
        while (group[u] != group[v]) {
            if (depth[u] > depth[v]) {
                cost = max(costBucket[u], cost);
                u = group[u];
            } else {
                cost = max(costBucket[v], cost);
                v = group[v];
            }
        }
        while (u != v) {
            if (depth[u] > depth[v]) {
                cost = max(cost, tcost[u]);
                u = parent[u];
            } else {
                cost = max(cost, tcost[v]);
                v = parent[v];
            }
        }
        printf("%d\n", cost);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}