题目链接


题解

题意

  • 给你一个无向图,求两个点之间的一条路径,使路径上的最小值最大

算法:Kruskal最大生成树+倍增lca

分析

  • 首先容易知道,答案一定在该图的最大生成树
  • 之后问题便转换成了树上点\(u\)到\(v\)的简单路径42中最小的边权
  • 经典的树上倍增
  • 用fa[i][j]来表示从第\(i\)个点往上\(2^j\)条边到达的点
  • 用s[i][j]来表示从第\(i\)个点往上\(2^j\)条边中的最小值
  • 答案就是在求lca的过程中统计一下最小值就可以了(具体详见代码)

复杂度

Kruskal \(O(m \log m)\)

倍增 \(O(n \log n)\)

总复杂度 \(O(n \log n + m \log m)\)

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
using namespace std; const int MAXN = 50050;
int n, m, q;
int p[MAXN];
int dep[MAXN], vis[MAXN], fa[MAXN][20], s[MAXN][20];
struct Edge
{
int u, v, w;
bool operator < (const Edge &_edge) const
{
return w > _edge.w;
}
}edge[MAXN];
int ecnt;
struct node
{
int v, w;
node *next;
}pool[MAXN], *head[MAXN];
void addedge(int u, int v, int w)
{
node *p = &pool[++ecnt], *q = &pool[++ecnt];
p->v = v, p->w = w, p->next = head[u], head[u] = p;
q->v = u, q->w = w, q->next = head[v], head[v] = q;
}
int find(int x)
{
if(p[x] == 0) return x;
else return p[x] = find(p[x]);
}
bool Union(int x, int y)
{
int px = find(x);
int py = find(y);
if(px == py)
return false;
p[px] = py;
return true;
}
void dfs(int u)
{
int v;
vis[u] = 1;
for(node *p = head[u]; p; p = p->next)
if(!vis[v = p->v])
{
dep[v] = dep[u] + 1;
fa[v][0] = u;
s[v][0] = p->w;
for(int j = 1; fa[v][j - 1] != 0; j++)
fa[v][j] = fa[fa[v][j - 1]][j - 1],
s[v][j] = min(s[v][j - 1], s[fa[v][j - 1]][j - 1]);
//预处理
dfs(v);
}
}
int query(int u, int v)//倍增
{
int ret = 2147483647;//返回值。因为求最小,所以初始赋最大
if(dep[u] < dep[v]) swap(u, v);
for(int i = 15; i >= 0; i--)
if(fa[u][i] != 0 && dep[fa[u][i]] >= dep[v])
ret = min(ret, s[u][i]), u = fa[u][i];//一定要先统计最小值
if(u == v) return ret;
for(int i = 15; i >= 0; i--)
if(fa[u][i] != fa[v][i])
ret = min(ret, min(s[u][i], s[v][i])), //统计最小
u = fa[u][i],
v = fa[v][i];
ret = min(ret, min(s[u][0], s[v][0]));//不要忘了最后还有两条边
return ret;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++)
scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w);
sort(edge + 1, edge + m + 1);
for(int i = 1; i <= m; i++)
if(Union(edge[i].u, edge[i].v))
addedge(edge[i].u, edge[i].v, edge[i].w);
dfs(1);
scanf("%d", &q);
for(int i = 1; i <= q; i++)
{
int u, v; scanf("%d%d", &u, &v);
if(find(u) != find(v))
{
printf("-1\n");
continue ;
}
printf("%d\n", query(u, v));
}
return 0;
}

题解 【luoguP1967 NOIp提高组2013 货车运输】的更多相关文章

  1. NOIP提高组 2013货车运输

    觉得题目水的离开 不屑的大佬请离开 不会图论的请离开 ……. 感谢您贡献的访问量 ————————————华丽的分割线———————————— 题面: 题目描述 A 国有 n 座城市,编号从 1 到 ...

  2. 【NOIP】提高组2013 货车运输

    [算法]最大生成树+LCA(倍增) [题解]两点间选择一条路径最小值最大的路径,这条路径一定在最大生成树上,因为最大生成树就是从边权最大的边开始加的. 先求原图的最大生成树(森林),重新构图,然后用一 ...

  3. 洛谷P1967 [NOIP2013提高组Day1T2]货车运输

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

  4. 【NOIP2013提高组】货车运输

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

  5. 洛谷P1966 火柴排队[NOIP提高组2013]

    我确信我应该是做过这道题……就当再写一遍好了. 贪心思想,一番证明得出a和b数组中最小对最小,次小对次小……时解最优.那么先处理出a,b之间的对应关系,然后按照该关系求a或者b的逆序对数量就是答案 / ...

  6. NOIP提高组2013 D2T3 【华容道】

    某王  老师给我们考了一场noip2013的真题...心态爆炸! 题目大意: 有一个n*m的棋盘,每个格子上都有一个棋子,有些格子上的棋子能够移动(可移动的棋子是固定的),棋盘中有一个格子是空的,仍何 ...

  7. NOIP 2013 货车运输【Kruskal + 树链剖分 + 线段树 】【倍增】

    NOIP 2013 货车运输[树链剖分] 树链剖分 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在 ...

  8. NOIP提高组2004 合并果子题解

    NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消 ...

  9. NOIP提高组历年真题题解

    2018 铺设道路 差分水题,推一下结论就好了. #include<cstdio> #include<algorithm> using namespace std; ],d[] ...

随机推荐

  1. Ext JS 6学习文档-第3章-基础组件

    Ext JS 6学习文档-第3章-基础组件 基础组件 在本章中,你将学习到一些 Ext JS 基础组件的使用.同时我们会结合所学创建一个小项目.这一章我们将学习以下知识点: 熟悉基本的组件 – 按钮, ...

  2. js经典试题之常用的方法

    js经典试题之常用的方法 1.下面代码输出的值 let s = "bob" const replaced = s.replace('b', 'l') replaced === &q ...

  3. ACM入门步骤(一)

    一般的入门顺序: 0. C语言的基本语法(或者直接开C++也行,当一个java选手可能会更受欢迎,并且以后工作好找,但是难度有点大),[参考书籍:刘汝佳的<算法竞赛入门经典>,C++入门可 ...

  4. .net平台借助第三方推送服务在推送Android,IOS消息(极光推送_V3版本)最新

    最近刚从极光推送官网上看到V2版本要停用,不得不有重新写V3版本的.这里用到了 HTTP Basic Authentication http://www.cnblogs.com/pingming/p/ ...

  5. MongoDb企业应用实战(一) 写在MongoDB应用介绍之前(ii)

    上一篇: MongoDb企业应用实战(一) 写在MongoDB应用介绍之前(i) 有段时间没跟大家去分享和探讨过一些问题,分享过一些经验了(失败过的,痛苦过的才最有看点啊,不知道各位同仁们怎么去看这个 ...

  6. Maven pom 文件解释

    1 - 什么是构建? 我们都知道,写完代码之后需要进行编译和运行,以笔者自身为例,使用 Eclipse 写完代码,需要进行编译,再生成 war 包,以便部署到 Tomcat. 在编写 Java 代码的 ...

  7. 第二章 IoC

    什么是IoC 如何配置IOC Bean的生命周期 多环境配置 条件化配置Bean 什么是IOC? IOC有两层含义, 1.控制反转:将对象实例的创建与销毁的权限交给Spring容器管理,而不再是调用对 ...

  8. java session特性

    1.当前浏览器不关闭 则一直有效 servlet就能取到值(未设置过期时间情况下 或者在过期的时间范围内)  算成一次会话 再次会话内多个请求都能获得session 2.session保存在服务端,通 ...

  9. BZOJ 2115 Xor(线性基)

    题意:给定一个n<=50000个点m<=100000条边的无向联通图,每条边上有一个权值wi<=1e18.请你求一条从1到n的路径,使得路径上的边的异或和最大. 任意一条1到n的路径 ...

  10. 【bzoj4579】[Usaco2016 Open]Closing the Farm 并查集

    题目描述 Farmer John and his cows are planning to leave town for a long vacation, and so FJ wants to tem ...