UVA12655 Trucks(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 fleet 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 first 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 indicating, 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

思路

先说题意,有n个点m条边的无向图,要进行货物运输,每条边长都有一个最大载重量,给出s组询问,问两个点之间的允许通过的最大载重量是多少。
比如样例1:
这里写图片描述
比如询问3 1,3可以通过走3 2 1这条道路,可以通过的最大载重量就是这条道路上的最小值,也就是8

要解决这个问题,我们首先要把这个图处理成一颗树,我们对整个无向图用kruskal求出最大生成树,这样最大的边就保留了。

接下来,用边建立一棵线段树,然后进行树链剖分即可

代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#include <list>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 2e5 + 10;
const int inf = 0x3f3f3f3f;
int first[N], tot;
int pre[N];
int MIN[N << 2];
int w[N], fa[N], dep[N], siz[N], son[N], top[N], id[N], cnt;
int n, m, s;
struct node
{
    int u, v, w;
} g[N];
struct edge
{
    int u, v, w, next;
} e[N * 2];
void init()
{
    mem(first, -1);
    tot = 0;
    cnt = 0;
    for (int i = 1; i <= n; i++)
        pre[i] = i;
}
void add_edge(int u, int v, int w)
{
    e[tot].u = u, e[tot].v = v, e[tot].w = w;
    e[tot].next = first[u];
    first[u] = tot++;
}
bool cmp(node a, node b)
{
    return a.w > b.w;
}
int find(int x)
{
    return x == pre[x] ? x : pre[x] = find(pre[x]);
}
int mix(int x, int y)
{
    int fx = find(x), fy = find(y);
    if (fx != fy)
    {
        pre[fy] = fx;
        return 1;
    }
    return 0;
}
void kruskal()
{
    int sum = 0;
    for (int i = 1; i <= m; i++)
    {
        if (mix(g[i].u, g[i].v))
        {
            sum++;
            add_edge(g[i].u, g[i].v, g[i].w);
            add_edge(g[i].v, g[i].u, g[i].w);
            //printf("%d-->%d=%d\n",g[i].u,g[i].v,g[i].w);
        }
        if (sum == n - 1)
            break;
    }
}
void pushup(int rt)
{
    MIN[rt] = min(MIN[rt << 1], MIN[rt << 1 | 1]);
}
void build(int l, int r, int rt)
{
    if (l == r)
    {
        MIN[rt] = w[l];
        return;
    }
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    pushup(rt);
}
int query(int L, int R, int l, int r, int rt)
{
    if (L <= l && r <= R)
        return MIN[rt];
    int m = (l + r) >> 1;
    int ans = inf;
    if (L <= m)
        ans = min(ans, query(L, R, lson));
    if (R > m)
        ans = min(ans, query(L, R, rson));
    return ans;
}
void dfs1(int u, int f, int deep)
{
    fa[u] = f;
    dep[u] = deep;
    siz[u] = 1;
    son[u] = 0;
    int maxson = -1;
    for (int i = first[u]; ~i; i = e[i].next)
    {
        int v = e[i].v;
        if (v == f)
            continue;
        dfs1(v, u, deep + 1);
        siz[u] += siz[v];
        if (siz[v] > maxson)
        {
            son[u] = v;
            maxson = siz[v];
        }
    }
}
void dfs2(int u, int topf)
{
    top[u] = topf;
    id[u] = ++cnt;
    if (!son[u])
        return;
    dfs2(son[u], topf);
    for (int i = first[u]; ~i; i = e[i].next)
    {
        int v = e[i].v;
        if (v == fa[u] || v == son[u])
            continue;
        dfs2(v, v);
    }
}
int qmin(int x, int y)
{
    int ans = inf;
    while (top[x] != top[y])
    {
        if (dep[top[x]] < dep[top[y]])
            swap(x, y);
        ans = min(ans, query(id[top[x]], id[x], 1, n, 1));
        x = fa[top[x]];
    }
    if (dep[x] > dep[y])
        swap(x, y);
    ans = min(ans, query(id[son[x]], id[y], 1, n, 1));
    return ans;
}
int main()
{
    //freopen("in.txt", "r", stdin);
    while (~scanf("%d%d%d", &n, &m, &s))
    {
        init();
        for (int i = 1; i <= m; i++)
            scanf("%d%d%d", &g[i].u, &g[i].v, &g[i].w);
        sort(g + 1, g + 1 + m, cmp);
        kruskal();
        dfs1(1, 0, 1);
        dfs2(1, 1);
        for (int i = 0; i < tot; i += 2)
        {
            if (dep[e[i].u] < dep[e[i].v])
                swap(e[i].u, e[i].v);
            w[id[e[i].u]] = e[i].w;
        }
        build(1, n, 1);
        int x, y;
        while (s--)
        {
            scanf("%d%d", &x, &y);
            printf("%d\n", qmin(x, y));
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/riba2534/article/details/81077559