题目链接

题目

题目描述

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

NC16527 [NOIP2013]货车运输的更多相关文章

  1. [Luogu 1967] NOIP2013 货车运输

    [Luogu 1967] NOIP2013 货车运输 一年多前令我十分头大的老题终于可以随手切掉了- 然而我这码风又变毒瘤了,我也很绝望. 看着一年前不带类不加空格不空行的清纯码风啊,时光也好像回去了 ...

  2. NOIP2013 货车运输(最大生成树,倍增)

    NOIP2013 货车运输(最大生成树,倍增) A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道 ...

  3. NOIP2013 货车运输 (最大生成树+树上倍增LCA)

    死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...

  4. NOIP2013 货车运输

    3.货车运输 (truck.cpp/c/pas) [问题描述] A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货 ...

  5. Codevs3278[NOIP2013]货车运输

    3287 货车运输 2013年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond      题目描述 Description A 国有 ...

  6. 【洛谷P1967】[NOIP2013]货车运输

    货车运输 题目链接 显然,从一点走到另一点的路径中,最小值最大的路径一定在它的最大生成树上 所以要先求出最大生成树,再在生成树上找最近公共祖先,同时求出最小值. #include<iostrea ...

  7. noip2013货车运输

    P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过 ...

  8. NOIP2013货车运输[lca&&kruskal]

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

  9. [noip2013]货车运输(kruskal + 树上倍增)

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

  10. [luogu P1967][NOIp2013] 货车运输

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

随机推荐

  1. 【C++】类成员冒号初始化以及构造函数内赋值

    From:https://blog.csdn.net/zj510/article/details/8135556 通常我们对类成员进行"初始化"有两种方式: 1. 构造函数后面跟冒 ...

  2. SpringMVC02——第一个MVC程序-配置版(low版)

    配置版 新建一个子项目,添加Web支持![在MVC01中有详细方法] 确定导入了SpringMVC的依赖 配置web.xml,注册DispatcherServlet <?xml version= ...

  3. [转帖]聊聊TPS、QPS、CPS概念和区别

    https://cloud.tencent.com/developer/article/1859053 TPS 概念 TPS:是TransactionsPerSecond的缩写,也就是事务数/秒.它是 ...

  4. [转帖]AnolisOS8安装ntp同步时间

    https://www.wlnmp.com/post-673.html 在AnolisOS8中默认不再支持ntp软件包,时间同步将由chrony来实现,如果你习惯了使用ntp来同步时间,一时难以去适应 ...

  5. [转帖]Unixbench的使用(综合性能测试、2D测试)和问题解决(跑不出多线程分数,调不出窗口,报错等)

    一.Unixbench简介 Unixbench一个基于系统的基准测试工具,不单纯是CPU 内存 或者磁盘测试工具.测试结果不仅仅取决于硬件,也取决于系统.开发库.甚至是编译器.Unixbench是一个 ...

  6. buildkit 官网 service 资料

    [Unit]   Description=BuildKit   Requires=buildkit.socket   After=buildkit.socket   Documentation=htt ...

  7. 使用rpm打包nacos然后部署为systemd服务开机自动启动的方法

    背景 Nacos是阿里开源的服务注册组件,能够简单的实现微服务的注册与发现机制. 但是官方并没有提供 sytemd的服务脚本, 也没有提供rpm包的方式. 公司里面使用 nacos的场景越来越多, 部 ...

  8. 谈JVM xmx, xms等内存相关参数合理性设置

    作者:京东零售 刘乐 说到JVM垃圾回收算法的两个优化标的:吞吐量和停顿时长,并提到这两个优化目标是有冲突的.那么有没有可能提高吞吐量而不影响停顿时长,甚至缩短停顿时长呢?答案是有可能的,提高内存占用 ...

  9. JavaScript一种新的数据结构类型Map

    什么是map 它类似于对象,是键值对的集合,但键的范围不局限在于字符串.各种类型的值(包含对象)都可以作为键. 如果同一个键被多次赋值,后面的值将会覆盖其那面的值.如果读取一个未知的键,返回的是und ...

  10. 【代码分享】使用 avx2 + 查表法,优化凯撒加密

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 接上一篇:[代码分享]使用 avx512 + 查表法,优化 ...