[NOIP2013/Codevs3287]货车运输-最小[大]生成树-树上倍增
Problem 树上倍增
题目大意
给出一个图,给出若干个点对u,v,求u,v的一条路径,该路径上最小的边权值最大。
Solution
看到这个题第一反应是图论。。
然而,任意路径最小的边权值最大,如果仔细思考的话就会知道,如果两个点相互连通,那么一定走的是最大生成树上的路径,而不会选择其他任何一条路径去走。
这个是可以非常简单证明的,就不再详述。
那么既然知道了这个,当然是先建一颗最大生成树啦!
现在问题来了,Prim&Kruskal,选哪个?
分析一下,prim复杂度$O(n^2)$,n为总点数。
Kruskal复杂度$O(m\log_2n)$,m为总边数。
显而易见,在这一道题目中kruskal更优。
于是写一个kruskal最大生成树。
接下来要在这颗树上跑。
我们设立一个fa数组,其fa[i][j]表示对于i节点,向上的2^j个节点编号是什么。显而易见,fa[i][0]就是i的父亲。
$$fa[i][j]=fa[fa[i][j-1][j-1]$$
然后我们还需要一个储存最小值的数组,设立minn数组,其中minn[i][j]表示对于i节点,向上2^j个节点的边最小值
显而易见,minn[i][0]就表示i节点本身链接父亲边的权值.
$$minn[i][j]=\min(minn[fa[i][j-1]][j-1],minn[i][j-1])$$
可以看出,这两个数组在O(n)的时间就可以求出来了。
接下来,对于每一个询问点对,我们只需要倍增求lca,再求两个点到lca路径上最小值,就可以求出答案。
判断uv谁深度更深,更深深度先跳到同一深度。
接下来两个一起向上跳,能够跳就跳。
具体方法可以看代码。
AC Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct kruskal{
int u,v,w;
}ekr[];
struct node{
int to,next,w;
}e[];
int f[],h[],dep[],n,m,u,v,w,q,ktot=,tot=,ans;
int fa[][],minn[][];
void add_kruskal(int u,int v,int w){
ekr[++ktot].u=u;ekr[ktot].v=v;ekr[ktot].w=w;
}
bool cmp(kruskal a,kruskal b){
return a.w>b.w;
}
void add(int u,int v,int w){
e[++tot].to=v;e[tot].next=h[u];h[u]=tot;e[tot].w=w;
e[++tot].to=u;e[tot].next=h[v];h[v]=tot;e[tot].w=w;
}
void initdfs(int x,int last,int we,int depth){
dep[x]=depth;
fa[x][]=last;
minn[x][]=we;
for(int i=;i<=;i++){
fa[x][i]=fa[fa[x][i-]][i-];
minn[x][i]=min(minn[x][i-],minn[fa[x][i-]][i-]);
}
for(int i=h[x];~i;i=e[i].next)
if(e[i].to!=last)initdfs(e[i].to,x,e[i].w,depth+);
}
void queue(int u,int v){
if(dep[u]<dep[v])swap(u,v);
int dist=dep[u]-dep[v],tmp=;
while(dist){
if(dist%==)ans=min(ans,minn[u][tmp]),u=fa[u][tmp];
tmp++;
dist>>=;
}
for(int i=;i>=;i--){
if(fa[u][i]!=fa[v][i]){
ans=min(min(ans,minn[u][i]),minn[v][i]);
u=fa[u][i];
v=fa[v][i];
}
}
ans=(u==v)?ans:min(min(ans,minn[u][]),minn[v][]);
}
int find(int x){
if(f[x]!=x)f[x]=find(f[x]);
return f[x];
}
int main(){
// freopen("xsy2018.in","r",stdin);
memset(h,-,sizeof(h));
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
add_kruskal(u,v,w);
}
sort(ekr+,ekr+ktot+,cmp);
for(int i=;i<=n;i++)f[i]=i;
for(int i=,sum=;i<=ktot;i++){
int fu=find(ekr[i].u),fv=find(ekr[i].v);
if(fu!=fv){
add(ekr[i].u,ekr[i].v,ekr[i].w);
f[fu]=fv;f[ekr[i].u]=fv;f[ekr[i].v]=fv;
sum++;
}
if(tot==((n-)<<))break;
}
initdfs(,,,);
scanf("%d",&q);
for(int i=;i<=q;i++){
scanf("%d%d",&u,&v);
ans=;
queue(u,v);
printf("%d\n",(ans==)?-:ans);
}
}
[NOIP2013/Codevs3287]货车运输-最小[大]生成树-树上倍增的更多相关文章
- NOIP2013 货车运输 (最大生成树+树上倍增LCA)
死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...
- NOIP2013 货车运输(最大生成树,倍增)
NOIP2013 货车运输(最大生成树,倍增) A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道 ...
- xsy 2018 【NOIP2013】货车运输
[NOIP2013]货车运输 Description A 国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有q辆货车在运输货物,司机们想知道每辆车在不超 ...
- 【NOIP2013/Codevs3287】货车运输-最小生成树(大)-树上倍增
https://www.luogu.org/problemnew/show/P1967 由题可知,我们走的路的边应尽可能大,所以通过kruscal建最大生成树的图,再树上倍增,注意可能有多棵树; #i ...
- 「NOIP2013」「LuoguP1967」货车运输(最大生成树 倍增 LCA
题目描述 AA国有nn座城市,编号从 11到nn,城市之间有 mm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最 ...
- NOIP2013 D1T3 货车运输 zz耻辱记
目录 先来证明下lemma: 图上2点间最小边权最大的路径一定在MST上 感性理解下: 每次kruskal algo都连接最大的不成环边 此时有2个未联通的联通块被连起来. 那么考虑u, v两点的联通 ...
- codevs3287货车运输(最小生成树+LCA)
3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description A 国有 ...
- C++之路进阶——codevs3287(货车运输)
3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description A 国有 n ...
- luogu1967 货车运输 最大瓶颈生成树
题目大意 给出一张图,给出q对点,求这两个点间权值最小边最大的路径,输出这个最小边权. 题解 我们先一条一条边建图.当建立的边使得图中形成环时,因为环中的每个节点只考虑是否连通和瓶颈大小,要想互相连通 ...
随机推荐
- DelayQueue使用
假设现有如下的使用场景: a) 关闭空闲连接.服务器中,有很多客户端的连接,空闲一段时间之后需要关闭之. b) 缓存.缓存中的对象,超过了空闲时间,需要从缓存中移出. c) 任务超时处理.在网络协议滑 ...
- 什么样的PPT能助你成为一个优秀的演讲者——程序员的演讲之道
欢迎访问我的个人博客,原文链接:http://wensibo.top/2017/05/28/speaker/ ,未经允许不得转载! 前言 今天是端午节假期的第一天,在这里祝大家假期快乐,不过像我这种渣 ...
- 如何在不使用系统函数的情况下实现PHP中数组系统函数的功能
PHP中为我们提供了各种各样的系统函数来实现我们需要的各种功能,那么,在不使用系统函数的情况下我们要怎样来实现这些功能呢?以下就是几种系统函数的实现方式. 首先,我们来定义一个数组: $arr= ar ...
- 为什么各大厂商要抢先跟进H.265?
继爱奇艺.乐视等视频厂商宣布支持 H.265 高清视频后,2014 年 4 月,搜狐视频宣布正式上线视频行业首个 H.265 高清大片专区,可在线观看 200 余部当下最火的超高清大片.国外 BBC ...
- Python Tkinter学习(1)——第一个Tkinter程序
注:本文可转载,转载请注明出处:http://www.cnblogs.com/collectionne/p/6885066.html.格式修改未完成. Tkinter资料 Python Wiki, T ...
- sql备份(导出脚本)
第一步: 右键需要备份的数据库(这里以MyDB为例)-->任务-->生成脚本
- Java之【线程通信】--标志位练习2
定义一个线程A,输出1 - 10之间的整数,定义一个线程B,逆序输出1 - 10之间的整数,要求线程A和线程B交替输出 方法一:非标志位方法 package Homework; //1 定义一个线程A ...
- python爬虫从入门到放弃(九)之 实例爬取上海高级人民法院网开庭公告数据
通过前面的文章已经学习了基本的爬虫知识,通过这个例子进行一下练习,毕竟前面文章的知识点只是一个 一个单独的散知识点,需要通过实际的例子进行融合 分析网站 其实爬虫最重要的是前面的分析网站,只有对要爬取 ...
- homebrew & brew cask使用技巧及Mac软件安装
homebrew 安装 /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/m ...
- Scheme实现二叉查找树及基本操作(添加、删除、并、交)
表转化成平衡二叉树 其中有一种分治的思想. (define (list->tree elements) (define (partial-tree elts n) (if (= n 0) (co ...