首页 > 其他分享 >NC16527 [NOIP2013]货车运输

NC16527 [NOIP2013]货车运输

时间:2023-06-23 11:35:18浏览次数:60  
标签:NOIP2013 int mi 货车运输 NC16527 fa 000 ans find

题目链接

题目

题目描述

A 国有 n 座城市,编号从 1 到 n ,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

输入描述

第一行有两个用一个空格隔开的整数 n,m ,表示 A 国有 n 座城市和 m 条道路。
接下来 m 行每行 3 个整数 x, y, z ,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意: x 不等于 y ,两座城市之间可能有多条道路 。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y 。

输出描述

共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出 -1 。

示例1

输入

4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3

输出

3
-1
3

备注

对于 30% 的数据, 0 < n < 1,000,0 < m < 10,000,0 < q< 1,000 ;
对于 60% 的数据, 0 < n < 1,000,0 < m < 50,000,0 < q< 1,000 ;
对于 100% 的数据, 0 < n < 10,000,0 < m < 50,000,0 < q< 30,000,0 ≤ z ≤ 100,000 。

题解

知识点:倍增,LCA,并查集,最小生成树。

显然,若两点有多条路径,我们一定选择一条最大生成树上的路径,这样保证走的每条边都是权值最大的,因此我们先求出最大生成树,代替原图。

然后就是查询任意两点路径的最小边,我们可以使用树剖,但是这里问题是静态的,因此用树上倍增会更好写。

注意,每次查询之前先判定两点是否连通,这个可以用并查集实现。

时间复杂度 \(O(m \log m + m \log n + q \log n)\)

空间复杂度 \(O(m+ n \log n)\)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

struct DSU {
    vector<int> fa;

    DSU(int n = 0) { init(n); }

    void init(int n) {
        fa.assign(n + 1, 0);
        iota(fa.begin(), fa.end(), 0);
    }

    int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }

    bool same(int x, int y) { return find(x) == find(y); }

    void merge(int x, int y) { fa[find(x)] = find(y); }
};

template<class T>
struct Graph {
    struct edge {
        int v, nxt;
        T w;
    };
    int idx;
    vector<int> h;
    vector<edge> e;

    Graph(int n = 0, int m = 0) { init(n, m); }

    void init(int n, int m) {
        idx = 0;
        h.assign(n + 1, 0);
        e.assign(m + 1, {});
    }

    void add(int u, int v, T w) {
        e[++idx] = { v,h[u],w };
        h[u] = idx;
    }
};

const int N = 10007, M = 50007;
Graph<int> g;

struct node {
    int u, v, w;
}e[M];

bool vis[N];
int f[27][N], mi[27][N], dep[N];
void dfs(int u, int fa, int faw) {
    vis[u] = 1;
    f[0][u] = fa;
    mi[0][u] = faw;
    dep[u] = dep[fa] + 1;
    for (int i = 1;i <= 20;i++) {
        f[i][u] = f[i - 1][f[i - 1][u]];
        mi[i][u] = min(mi[i - 1][u], mi[i - 1][f[i - 1][u]]);
    }
    for (int i = g.h[u];i;i = g.e[i].nxt) {
        int v = g.e[i].v, w = g.e[i].w;
        if (vis[v]) continue;
        dfs(v, u, w);
    }
}

int get_ans(int u, int v) {
    int ans = 1e9;
    if (dep[u] < dep[v]) swap(u, v);
    for (int i = 20;i >= 0;i--) {
        if (dep[f[i][u]] >= dep[v]) {
            ans = min(ans, mi[i][u]);
            u = f[i][u];
        }
        if (u == v) return ans;
    }
    for (int i = 20;i >= 0;i--) {
        if (f[i][u] != f[i][v]) {
            ans = min({ ans, mi[i][u], mi[i][v] });
            u = f[i][u];
            v = f[i][v];
        }
    }
    return min({ ans, mi[0][u], mi[0][v] });
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, m;
    cin >> n >> m;
    for (int i = 1;i <= m;i++) {
        int u, v, w;
        cin >> u >> v >> w;
        e[i] = { u,v,w };
    }
    sort(e + 1, e + m + 1, [&](const node &a, const node &b) {return a.w > b.w;});
    DSU dsu(n);
    g.init(n, n << 1);
    for (int i = 1;i <= m;i++) {
        auto [u, v, w] = e[i];
        if (dsu.same(u, v)) continue;
        dsu.merge(u, v);
        g.add(u, v, w);
        g.add(v, u, w);
    }

    for (int i = 1;i <= n;i++) if (!vis[i]) dfs(i, 0, 0);

    int q;
    cin >> q;
    while (q--) {
        int u, v;
        cin >> u >> v;
        if (!dsu.same(u, v)) cout << -1 << '\n';
        else cout << get_ans(u, v) << '\n';
    }
    return 0;
}

标签:NOIP2013,int,mi,货车运输,NC16527,fa,000,ans,find
From: https://www.cnblogs.com/BlankYang/p/17498902.html

相关文章

  • 【题解】Luogu[P1967] NOIP2013 提高组 货车运输
    Link→很容易想到一个暴力做法,就是跑一遍Floyd,\(F_{i,j}\)表示\(i\)到\(j\)最大载重量,转移\(F_{i,j}=\max\{F_{i,j},\min\{F_{i,k},F_{k,j}\}\}\)。显然时间复杂度\(O(n^3)\)是过不了的。我们发现,因为是求两点路径中使得最小值最大,实际上有一些较小的路径是不会走......
  • [NOIP2013 普及组] 表达式求值
    [NOIP2013普及组]表达式求值题目描述给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值。输入格式一行,为需要你计算的表达式,表达式中只包含数字、加法运算符“\(+\)”和乘法运算符“$\times$”,且没有括号,所有参与运算的数字均为\(0\)到\(2^{31}-1\)之......
  • 洛谷 P1967 货车运输
    P1967NOIP2013提高组]货车运输-洛谷|计算机科学教育新生态(luogu.com.cn)这个题目算是lca的稍微拓展吧。主要思考方向应该是很明显的。就是考虑一条路径上权值最......
  • P1983 [NOIP2013 普及组] 车站分级
    P1983[NOIP2013普及组]车站分级https://www.luogu.com.cn/problem/P1983 思路https://www.cnblogs.com/tomori/p/14331510.html   Codehttps://www.luo......
  • m基于ACO蚁群优化的货车运输路线规划matlab仿真,考虑车辆载重,单位运输成本等因素
    1.算法描述蚁群算法是通过对自然界中真实蚂蚁的集体行为的观察,模拟而得到一种仿生优化算法,它具有很好的并行性,分布性.根据蚂蚁群体不同的集体行为特征,蚁群算法可分为受......
  • m基于ACO蚁群优化的货车运输路线规划matlab仿真,考虑车辆载重,单位运输成本等因素
    1.算法描述      蚁群算法是通过对自然界中真实蚂蚁的集体行为的观察,模拟而得到一种仿生优化算法,它具有很好的并行性,分布性.根据蚂蚁群体不同的集体行为特征,蚁......
  • P1980 [NOIP2013 普及组] 计数问题
    题目链接:https://www.luogu.com.cn/problem/P1980术语以下的英文术语均可以翻译为数字。digit:一个数字字符,十进制就是0-9之间的一个字符;numeral:用来表示数字的......
  • P1967 [NOIP2013 提高组] 货车运输 做题记录
    套路题了。根据和角公式\(\mathrm{\sin(\alpha+\beta)=\sin\alpha\cos\beta+\cos\alpha\cos\beta,\cos(\alpha+\beta)=\cos\alpha\cos\beta-\si......
  • NC16541 [NOIP2013]车站分级
    题目链接题目题目描述一条单向的铁路线上,依次有编号为1,2,…,n的n个火车站。每个火车站都有一个级别,最低为1级。现有若干趟车次在这条线路上行驶,每一趟都满足如下......
  • [NOIP2013 提高组] 货车运输 题解
    [NOIP2013提高组]货车运输题解本题解介绍一种最大生成树+并查集+启发式合并离线的做法。想法题目要多次求两点之间的最大瓶颈路长度,所以可以先参照最小瓶颈路的通......