codevs3287: [NOIP2013]货车运输

来源:互联网 发布:php split 空格 编辑:程序博客网 时间:2024/04/28 11:36

题目链接
最大生成树+LCA。
静态LCA,数据离线,可以用tarjan或者倍增。
然而
我写了树链剖分

#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int N = 10010;struct edge{    int u, v, w;    inline bool operator < (const edge &rhs) const {        return w > rhs.w;    }}lib[N * 5];int n, m, q;vector<edge> E[N];#define pb push_backint pa[N];int find(int x) {    return pa[x] == x ? x : pa[x] = find(pa[x]);}inline void kruskal() {    for (int i = 1; i <= n; i++) pa[i] = i;    sort(lib + 1, lib + 1 + m);    int eCnt;    for (int i = 1; i <= m; i++) {        int &u = lib[i].u, &v = lib[i].v, &w = lib[i].w;        int rA = find(u), rB = find(v);        if (rA == rB) continue;             pa[rA] = rB; eCnt++;        E[u].pb((edge){u, v, w});        E[v].pb((edge){v, u, w});        if (eCnt == n - 1) break;    }}int dep[N], size[N], son[N], fa[N], top[N], seg[N], segCnt, tree[N], wt[N];void dfs1(int u, int f) {    size[u] = 1; dep[u] = dep[f] + 1; fa[u] = f;    for (int i = 0; i < E[u].size(); i++) {        int &v = E[u][i].v, &w = E[u][i].w;        if (v == f) continue;        dfs1(v, u);        size[u] += size[v];        if (size[son[u]] < size[v])            son[u] = v;        wt[v] = w;    }}void dfs2(int u, int tp) {    top[u] = tp; seg[u] = ++segCnt; tree[seg[u]] = u;    if (! son[u]) return;    dfs2(son[u], tp);    for (int i = 0; i < E[u].size(); i++) {        int &v = E[u][i].v;        if (v == fa[u] or v == son[u]) continue;        dfs2(v, v);    }}int val[N<<1];#define g(l, r) (l + r | l != r)#define o g(l, r)#define ls g(l, mid)#define rs g(mid + 1, r)int gl, gr, gx;#define set(l, r) gl = l, gr = rinline void update(int l, int r) {    int mid = l + r >> 1;    val[o] = min(val[ls], val[rs]);}void buildTree(int l, int r) {    if (l == r) {        val[o] = wt[tree[l]];        return;    }    int mid = l + r >> 1;    buildTree(l, mid);    buildTree(mid + 1, r);    update(l, r);}inline void preWork() {    kruskal();    for (int i = 1; i <= n; i++)        if (pa[i] == i) {            dfs1(i, 0);            dfs2(i, i);        }    buildTree(1, n);}void query(int l, int r) {    if (gl <= l and r <= gr) {        gx = min(gx, val[o]);        return;    }    int mid = l + r >> 1;    if (gl <= mid) query(l, mid);    if (gr >= mid + 1) query(mid + 1, r);}inline int Query(int u, int v) {    gx = 100001;    int f1 = top[u], f2 = top[v];    while (f1 != f2) {        if (dep[f1] < dep[f2]) {            swap(u, v); swap(f1, f2);        }        set(seg[f1], seg[u]); query(1, n);        u = fa[f1], f1 = top[u];    }    if (u != v) {        if (dep[u] > dep[v]) swap(u, v);        set(seg[son[u]], seg[v]); query(1, n);    }    return gx;}inline void mainWork() {    cin >> q;    while (q--) {        int u, v; scanf("%d%d", &u, &v);        printf("%d\n", find(u) != find(v) ? -1 : Query(u, v));    }}int main() {    cin >> n >> m;    for (int i = 1; i <= m; i++) {        int a, b, w; scanf("%d%d%d", &a, &b, &w);        lib[i] = (edge){a, b, w};    }    preWork();    mainWork();    return 0;}
0 0