题目链接

https://www.luogu.org/problemnew/show/P1967

分析

NOIp的一道裸题,直接在最大生成树上剖分取最小值一下就完事了,非常好写,常数也比较小,然而题解里有许多我没见过的船新操作,先挖个坑等有时间再看

注意

  • 树链剖分又在第一遍挂了,忘了写top[now]=t;

  • 注意题目说明并没有保证是联通的!!!然后成功被Hack了.这真的要警惕,指不定哪天毒瘤出题人就在这里把你正解卡成60(flag++)

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <vector>
#include <queue>
#define ll long ong
#define ri register int
#define ull unsigned long long
using std::vector;
using std::swap;
using std::min;
using std::max;
using std::sort;
template <class T>inline void read(T &x){x=0;int ne=0;char c;while(!isdigit(c=getchar()))ne=c=='-';x=c-48;while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;x=ne?-x:x;return ;
}
const int maxn=10005;
const int maxm=50005;
const int inf=0x7fffffff;
int n,m;
struct Edge{int x,y,c;Edge(int _x,int _y,int _c){x=_x,y=_y,c=_c;}Edge(){x=y=c=0;}bool operator <(const Edge &b)const {return c>b.c;}
}edge[maxm];
struct Dat{int ver,dis;Dat(int x,int y){ver=x,dis=y;}Dat(){;}
};
vector<Dat>g[maxn];
int pa[maxn];
int get(int x){if(pa[x]!=x)pa[x]=get(pa[x]);//return pa[x]==x?pa[x]:pa[x]=get(pa[x]);return pa[x];
}
inline void kruskal(){int cnt=0,x,y,xx,yy,c;sort(edge+1,edge+1+m);for(ri i=1;i<=n;i++)pa[i]=i;for(ri i=1;i<=m;i++){//printf("%d\n",edge[i].c);int x=edge[i].x,y=edge[i].y;xx=get(x),yy=get(y);if(xx==yy)continue;c=edge[i].c;//printf("%d %d %d\n",x,y,c);g[x].push_back(Dat(y,c));g[y].push_back(Dat(x,c));pa[xx]=yy;cnt++;if(cnt==n-1)break;}return ;
}
int dep[maxn],son[maxn],top[maxn],size[maxn],dfn[maxn],fa[maxn],rnk[maxn],tot=0;
int w[maxn];
void dfs_1(int now){int v;size[now]=1;for(ri i=0;i<g[now].size();i++){v=g[now][i].ver;if(v==fa[now])continue;fa[v]=now,dep[v]=dep[now]+1;w[v]=g[now][i].dis;dfs_1(v);size[now]+=size[v];if(!son[now]||size[v]>size[son[now]])son[now]=v;}return ;
}
void dfs_2(int now,int t){int v;dfn[now]=++tot,rnk[tot]=now,top[now]=t;if(!son[now])return ;dfs_2(son[now],t);for(ri i=0;i<g[now].size();i++){v=g[now][i].ver;if(v==fa[now]|v==son[now])continue;dfs_2(v,v);}return ;
}
int mi[maxn<<2];
void build(int now,int l,int r){if(l==r){mi[now]=w[rnk[l]];return ;}int mid=(l+r)>>1;build(now<<1,l,mid);build(now<<1|1,mid+1,r);mi[now]=min(mi[now<<1],mi[now<<1|1]);return ;
}
int L,R;
int query(int now,int l,int r){if(L<=l&&r<=R){return mi[now];}int ans=inf,mid=(l+r)>>1;if(L<=mid)ans=min(ans,query(now<<1,l,mid));if(mid<R)ans=min(ans,query(now<<1|1,mid+1,r));return ans;
}
inline int query_path(int x,int y){int ans=inf;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);L=dfn[top[x]],R=dfn[x];ans=min(ans,query(1,1,n));x=fa[top[x]];}if(dfn[x]>dfn[y])swap(x,y);L=dfn[x]+1,R=dfn[y];if(L>R)return ans;ans=min(ans,query(1,1,n));return ans;
}
int main(){int q,x,y,z;read(n),read(m);for(ri i=1;i<=m;i++){read(x),read(y),read(z);edge[i]=Edge(x,y,z);}kruskal();for(ri i=1;i<=n;i++){//不一定联通if(!dfn[i]){dep[i]=1,fa[i]=0;dfs_1(i);dfs_2(i,i);}}build(1,1,n);read(q);while(q--){read(x),read(y);int tmp=query_path(x,y);if(!tmp)puts("-1");else printf("%d\n",tmp);}return 0;
}

转载于:https://www.cnblogs.com/Rye-Catcher/p/9428155.html

luogu题解P1967货车运输--树链剖分相关推荐

  1. 树链剖分概念及模板 + 例题 [POJ3237 tree + 软件包管理器]

    文章目录 概念 模板 例题1:软件包管理器 题目 题解 代码实现 例题2:POJ3237 tree 题目 题解 代码实现 概念 树链剖分主要是用于解决以下这两个问题. 1.更改树上点x到点y的最短路径 ...

  2. hdu 3966(树链剖分+线段树区间更新)

    传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...

  3. 洛谷3384:【模板】树链剖分——题解

    https://www.luogu.org/problemnew/show/P3384 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 ...

  4. 【树链剖分】染色(luogu 2486/金牌导航 树链剖分-3)

    正题 luogu 2486 金牌导航 树链剖分-3 题目大意 给你一棵树,让你进行以下操作: 1.把一条路径染上一个颜色 2.查询一条路径上有多少个颜色段 解题思路 用树链剖分把问题转化为链上问题 然 ...

  5. 【树链剖分】软件管理(luogu 2146/金牌导航 树链剖分-2)

    正题 luogu 2146 金牌导航 树链剖分-2 题目大意 有若干软件,除了软件0,所有软件都依赖且只依赖于另外一个软件 当要删除一个软件时,所有依赖于该软件的软件都要删掉 当安装一个软件时,该软件 ...

  6. 【树链剖分】旅游(luogu 3976)

    正题 luogu 3976 题目大意 给你一棵树,每个点有一个权值s 现在给你一条路径,让你选择两个点x,y,使y在x后面,且sy−sxs_y-s_xsy​−sx​最大 然后该路劲上所有点权值加v 解 ...

  7. 【树链剖分】Disruption P(luogu 4374)

    正题 luogu 4374 题目大意 给你一棵树,还有若干边,每条边有一定代价,问你删掉树中的每条边后,使其成为连通图的最小代价 解题思路 不难发现,一条边只对两个端点在树中的路径上的边有贡献(即删去 ...

  8. Luogu P5556 圣剑护符(线性基,树链剖分,线段树)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Problem 小L 和 小K 面前的圣剑由 nnn 块护符组成,分别编号为 1,2,-,n1,2,\ ...

  9. luogu P3398 仓鼠找sugar(树链剖分、求树上两条路径有没有交点,爽!)

    整理的算法模板合集: ACM模板 舒服,一次敲160行代码一次编译通过一次AC是真的爽! 虽然这道题可以当作简单版的树链剖分板子题了hhh 要求的是两条路径有没有交点,正解是LCA玄学证明,看的我有点 ...

  10. 【Luogu】P3950部落冲突(树链剖分)

    题目链接 状态奇差无比,sbt都能错一遍. 不动笔光想没有想到怎么做,画图之后发现一个很明显的性质-- 那就是两个开战的部落,其中一个是另一个的父亲. 所以在儿子那里加个权值.查询的时候树链剖分查询链 ...

最新文章

  1. 暴 雨 雲 于 7月17日
  2. Silverlight 控件开发记录之 extern alias” 关键字
  3. python代码教程-【Python】Python3纯代码极简教程
  4. Error: The 'decorators' plugin requires a 'decoratorsBeforeExport' option
  5. MongoDB 的 upsert
  6. 2019长江课堂作业答案_“绝户网”捕捞长江鳗鱼苗 检察机关:“全链条”担责...
  7. 像孙正义为了练英语坚决不说日语一样。我也应该有坚决不看中文文档的心!...
  8. 解决Linux下chrome无法播放flash问题
  9. 十分钟弄懂字节对编码
  10. Twitter数据抓取的方法(一)
  11. 使用高斯金字塔和拉普拉斯金字塔重构图像(matlab代码)
  12. 【优化算法】白冠鸡优化算法(COOT)【含Matlab源码 1795期】
  13. 更新linux gcc版本到gcc 4.4.2
  14. SPRING IN ACTION 第4版笔记-第十章Hitting the database with spring and jdbc-002-本章的源代码...
  15. 区块链技术可简化房地产交易流程
  16. Tp5.0对接腾讯云语音验证码
  17. 零基础学java的最佳学习方法
  18. 一个大一程序员的反思
  19. 计算方法 差商与牛顿插值
  20. Layui表单复选框验证

热门文章

  1. vue学习-路由router
  2. linux查看硬盘分区类型,linux 下查看硬盘分区类型
  3. Hibernate工作流程及与 MyBatis的比较
  4. linux中目录的作用是什么,在linux文件系统中,/etc 目录的作用到底是干什么用的?...
  5. 阶段5 3.微服务项目【学成在线】_day02 CMS前端开发_06-vuejs研究-vuejs基础-v-on指令...
  6. NOIP模拟题 栅栏
  7. 设置指定打印机端口打印
  8. 收获,不止oracle
  9. react入门----事件监听
  10. HDU 1527 取石子游戏