UVA 12655 Trucks(MST + LCA)

来源:互联网 发布:报纸编辑排版软件 编辑:程序博客网 时间:2024/06/06 21:06

uva 12655 Trucks [LCA](树链剖分+MST)

The Subtle Balloons Company (SBC) is the main balloon provider for programming contests; it has
huge factories and warehouses, as well as an extensive truck 
eet to ensure the contestants' happiness.
There are lots of competition sites in Nlogonia, and all of them hired SBC for supplying balloons for
their contests. Nlogonia is an archipelago connected by several bridges. Every island of Nlogonia may
have several regional sites and may also house several SBC warehouses.
When planning the routes for balloon deliveries, SBC faced a problem: for safety issues, every
bridge in Nlogonia has some maximum weight limit for vehicles which cross it. And because of the
great net weight of the transported merchandise, SBC operations' chief asked you to write a program to
determine the maximum weight allowed to be transported between warehouses and competition sites.
Input
The input contains several test cases. The rst line of a test case contains three integers N, M and S
which indicate, respectively, the number of islands, the number of bridges that connect the islands and
the number of sites. The islands are numbered from 1 to N.
Each of the next M lines describes a bridge. The description of a bridge consists in a line with
three integers A, B and W, indicating respectively the two islands connected by the bridge and the
maximum weight allowed in that bridge, in tons.
All bridges are two-way roads; every pair of islands is connected by at most one bridge; and it is
possible to reach every other island in the archipelago using only bridges (naturally it may be needed
to pass through other islands to do so).
Each of the next S lines describe a competition site and contains two integers L and H indicat-
ing, respectively, the number of the island where this site is and the number of the island where the
wharehouse which will be used to deliver the balloons to the site is.
Output
For each site in a test case, in the order they were given, your program must produce a single line,
containing a single integer, the biggest weight which can be transported by truck from the warehouse
to the site.
Restrictions

• 2 ≤ N ≤ 2 × 104
• 1 ≤ M ≤ 105
• 1 ≤ S ≤ 5 × 104
• 1 ≤ A, B, L, H ≤ N, A ̸= B, L ̸= H
• 0 ≤ W ≤ 105


Sample Input
4 5 4
1 2 9
1 3 0
2 3 8
2 4 7
3 4 4
1 4
2 1
3 1
4 3
4 5 2
1 2 30
2 3 20
3 4 10
4 1 40
2 4 50
1 3
1 2


Sample Output
7
9
8
7
20
40

 给你一个无向图,然后查询各点之间连接最大值,的路径上的最小值。。


先求一个最大生成树,然后树链剖分 线段树维护

#include <iostream>#include <stdio.h>#include <string.h>#include <map>#include <algorithm>using namespace std;const int maxn = 10050;const int INF = 0x3f3f3f3f;int n, m, s;int fa[maxn], son[maxn], son_num[maxn], pre[maxn], top[maxn], pos[maxn], fpos[maxn], deep[maxn];int head[maxn], total, cur_pos;struct Edge {    int u, v, w, next;}edge[maxn * 20];struct Node {    int u, v, w;    bool operator < (const Node& n) const {        return n.w < w;    }}node[maxn * 20];void add(int u, int v, int w) {    edge[total] = {u, v, w, head[u]};    head[u] = total++;    edge[total] = {v, u, w, head[v]};    head[v] = total++;}void init() {    for (int i = 1; i < maxn; ++i) {        fa[i] = i;    }    memset(head, -1, sizeof(head));    memset(son, -1, sizeof(son));    total = cur_pos = 0;}int find(int x) {    if (fa[x] == x)        return x;    return fa[x] = find(fa[x]);}int Kruskal() {    sort(node, node + m);    int j = 0;    for (int i = 0; i < m; ++i) {        int fu = find(node[i].u), fv = find(node[i].v);        if (fu != fv) {            j++;            fa[fu] = fv;            add(node[i].u, node[i].v, node[i].w);        }    }    return j;}void dfs(int u, int f, int d) {    son_num[u] = 1;    deep[u] = d;    pre[u] = f;        for (int i = head[u]; i != -1; i = edge[i].next) {        int v = edge[i].v;        if (v != f) {            dfs(v, u, d + 1);            son_num[u] += son_num[v];            if (son[u] == -1 || son_num[son[u]] < son_num[v]) {                son[u] = v;            }        }    }}void get_pos(int u, int sp) {    top[u] = sp;    pos[u] = ++cur_pos;    ::fpos[pos[u]] = u;    if (son[u] != -1)        get_pos(son[u], sp);    for (int i = head[u]; i != -1; i = edge[i].next) {        int v = edge[i].v;        if (v != pre[u] && v != son[u])            get_pos(v, v);    }}struct SegTree {    int left, right, min;}tree[maxn << 2];void push_up(int i) {    tree[i].min = min(tree[i << 1].min, tree[i << 1 | 1].min);}void build(int i, int l, int r) {    tree[i].left = l;    tree[i].right = r;    if (l == r) {        tree[i].min = INF;        return;    }    int mid = (l + r) >> 1;    build(i << 1, l, mid);    build(i << 1 | 1, mid + 1, r);}void update(int i, int k, int val) {    if (tree[i].left == k && tree[i].right == k) {        tree[i].min = val;        return;    }    int mid = (tree[i].left + tree[i].right) >> 1;    if (mid >= k)        update(i << 1, k, val);    else        update(i << 1 | 1, k, val);    push_up(i);}int query(int i, int b, int e) {    if (tree[i].left >= b && tree[i].right <= e)        return tree[i].min;    int res = INF;    int mid = (tree[i].left + tree[i].right) >> 1;    if (mid >= b)        res = min(res, query(i << 1, b, e));    if (mid < e)        res = min(res, query(i << 1 | 1, b, e));    return res;}int get_ans(int u, int v) {    int fu = top[u], fv = top[v];    int res = INF;    while (fu != fv) {        if (deep[fu] < deep[fv]) {            swap(u, v);            swap(fu, fv);        }        res = min(res, query(1, pos[fu], pos[u]));        u = pre[fu];        fu = top[u];    }    if (deep[u] < deep[v])        swap(u, v);        //cout << u << "    " << v << endl;    if (u != v)        res = min(res, query(1, pos[v] + 1, pos[u]));    return res;}int main() {        //freopen("in.txt", "r", stdin);    while (cin >> n >> m >> s) {        init();        for (int i = 0; i < m; ++i) {            cin >> node[i].u >> node[i].v >> node[i].w;        }        Kruskal();        dfs(1, -1, 1);        get_pos(1, 1);        build(1, 1, cur_pos);            for (int i = 0, j = 0; i < n - 1; ++i, j += 2) {            int u = edge[j].u, v = edge[j].v;            if (deep[u] < deep[v])                swap(u, v);            update(1, pos[u], edge[j].w);        }            while (s--) {            int u, v;            cin >> u >> v;            cout << get_ans(u, v) << endl;        }    }}


原创粉丝点击