题目链接

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

luogu题解P1967货车运输--树链剖分的更多相关文章

  1. P1967 货车运输 树链剖分

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

  2. luogu题解P2486[SDOI2011]染色--树链剖分+trick

    题目链接 https://www.luogu.org/problemnew/show/P2486 分析 看上去又是一道强行把序列上问题搬运到树上的裸题,然而分析之后发现并不然... 首先我们考虑如何在 ...

  3. luogu题解 P3950部落冲突--树链剖分

    题目链接 https://www.luogu.org/problemnew/show/P3950 分析 大佬都用LCT,我太弱只会树链剖分 一个很裸的维护边权树链剖分题.按照套路,对于一条边\(< ...

  4. 【Luogu】P3313旅行(树链剖分)

    题目链接 动态开点的树链剖分qwq. 跟小奇的花园一模一样,不做过多讲解. #include<cstdio> #include<cstring> #include<cct ...

  5. Luogu 3384 【模板】树链剖分

    题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...

  6. 树链剖分 - Luogu 3384【模板】树链剖分

    [模板]树链剖分 题目描述 已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操 ...

  7. Luogu P3178 树上操作(树链剖分+线段树)

    题意 见原题 题解 重链剖分模板题 #include <cstdio> #include <algorithm> using std::swap; typedef long l ...

  8. 【Luogu】P3979遥远的国度(树链剖分)

    题目链接 不会换根从暑假开始就困扰我了……拖到现在…… 会了还是很激动的. 换根操作事实上不需要(也不能)改树剖本来的dfs序……只是在query上动动手脚…… 设全树的集合为G,以root为根,u在 ...

  9. 题解 P1967 货车运输

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

随机推荐

  1. GPS nmealib学习 问题

    When building on Ubuntu 12.x the build fails with the following error… gcc  samples/generate/main.o ...

  2. 【421】C语言输入输出函数说明

    目录: sscanf & sprintf scanf & printf getchar & putchar fgets & fputs fscanf & fpr ...

  3. pycharm重命名文件

    先右键要重命名的文件,然后按照下图操作:

  4. vmware安装密钥

    VMware虚拟机已升级至14版本,之前的12版本的秘钥已经无法使用,在此分享一下VMware Workstation 14永久激活密钥: CG54H-D8D0H-H8DHY-C6X7X-N2KG6 ...

  5. JMETER安装教程

    jmeter的安装教程 1:安装jdk并且配置好环境变量,此处就不做赘述(前面的文档中有) 2:下载jmeter文件和jmeter的插件文件 JMeter:http://jmeter.apache.o ...

  6. some code about numpy and notes about copy&broadcasting

    import numpy as np np.__version__ #版本 #由于python的list不要求存储同样的类型,但是效率不高. L = [i for i in range(10)] L[ ...

  7. ES6 中 let 和 const 总结

    目录 let const 1. let要好好用 1. 基本用法 2. let声明的变量不存在变量提升 3. TDZ(temporal dead zone)暂时性死区 4. 不允许重复声明 2. 块级作 ...

  8. 项目中微信公众号调取支付控件demo

    微信支付官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6 前端代码demo (JSP页面): ...

  9. python 字典dict - python基础入门(15)

    前面的课程讲解了字符串str/列表list/元组tuple,还有最后一种比较重要的数据类型也需要介绍介绍,那就是python字典,俗称:dict. python中的字典可与字符串/列表/元组不同,因为 ...

  10. python+unittest框架第三天unittest之分离测试固件和公共代码,跳过案例的执行

    我们在时间工作中,会将整个项目的代码分别放置多个模块中去编写.方便后期项目维护,比如,我们的web项目可能有多个IP地址,每个IP地址代表不同的测试环境.测试环境与Bat环境或者验收环境等.这就需要我 ...