UVA 12655 Trucks(MST + LCA)

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;
        }
    }
}


### 回答1: 汽车和卡车收藏是一种热门的爱好,很多人对汽车和卡车的设计、功能和历史感兴趣。收藏汽车和卡车可以带来很多的乐趣和满足感。 首先,汽车和卡车的收藏可以展示个人的品味和独特性。不同的人对汽车和卡车的喜好不同,一些人可能喜欢豪华轿车,而另一些人可能更喜欢越野卡车或老式经典车型。通过收集自己喜爱的汽车和卡车,可以展示自己的个性和独特的品味。 其次,汽车和卡车的收藏可以成为一个有趣的学习经历。了解每辆车的历史、制造商和技术等方面的知识可以增加对汽车和卡车的理解和欣赏。收藏家可以通过阅读书籍、参观展览和参与车展等活动来不断学习和了解更多关于汽车和卡车的信息。 此外,汽车和卡车的收藏还可以成为一种投资。某些汽车和卡车的价值会随着时间的推移而增加,特别是限量版或稀有的车型。因此,一些收藏家把汽车和卡车视为一种投资手段,期望在未来可以获得更高的投资回报。 最后,汽车和卡车的收藏可以带来社交互动。收藏家可以通过参加汽车和卡车俱乐部、交流论坛和展览会等活动,与其他对汽车和卡车感兴趣的人交流、分享经验和建立友谊。这些互动可以使收藏家们感受到彼此的共鸣和激情,并且可以与志同道合的人一起分享乐趣。 总之,汽车和卡车的收藏是一个有趣的爱好。通过收集汽车和卡车,收藏家可以展示个人品味和独特性,同时也可以通过学习和投资获得乐趣和满足感,与其他对汽车和卡车感兴趣的人建立社交互动。 ### 回答2: 车辆收藏是指收集各种汽车和卡车以展示其独特的设计、工艺和历史价值。这种收藏爱好可以追溯到汽车的问世,是全球各地许多人的热衷。 汽车和卡车的收集有许多不同的动机。一些人可能喜欢车辆的外观和性能,将其视为艺术品。他们可能会寻找经典或稀有的车辆,以展示其独特的设计风格和工艺。通过这种收藏,人们可以欣赏汽车与时代的互动,了解汽车行业的发展和演变。 另外,汽车收藏也可以是人们的投资。一些经典车辆的价值会随着时间的推移而增长,成为非常有价值的资产。有些汽车爱好者将其收藏当作一种投资策略,希望在未来能够通过出售收藏的汽车获得丰厚的回报。 此外,汽车和卡车的收藏也可以作为一个兴趣爱好和社交活动。汽车展览和聚会是这些收藏者们展示自己收藏品、交流车辆知识和结识志同道合的人的地方。这些活动为汽车爱好者提供了一个交流和学习的平台,使他们能够深入了解汽车文化和历史。 总的来说,汽车和卡车的收藏是一种多样化的兴趣爱好,它们通过独特的设计、工艺和历史价值吸引着人们。车辆收藏不仅是对汽车文化和历史的了解,也可以带来投资和社交的机会。无论是出于艺术追求还是经济考量,汽车和卡车收藏都是一个引人入胜且富有价值的领域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值