题目链接

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. MySQL之二进制日志

    一.Binlog日志格式 根据日志定义的格式不一样,可以分为Statement格式.Row格式或者MIXED格式 mysql5.6----> | binlog_format | STATEMEN ...

  2. 算法习题---4.4信息解码(UVa213)

    一:题目 消息编码方案要求在两个部分中发送一个被编码的消息.第一部分:称为头,包含消息的字符.第二部分包含一个模式 表示信息.你必须写一个程序,可以解码这个消息. (一)题目详细 你的程序的编码方案的 ...

  3. Ubunut16.04 安装 g++ gcc 降级

    1. 查看gcc版本和g++版本 cd /usr/bin ls -l gcc* ls -l g++* 2. 安装gcc和g++ 4.4版本 sudo apt-get install gcc-4.4 g ...

  4. 关于appium操作真机打开app之后无法定位页面元素的问题的解决办法

    appium操作真机打开app后无法定位页面元素:例如微信或者支付宝支付时,手机的安全控件会对支付环境进行保护,会断掉当前appium与真机的链接,导致连接失败,无法定位到页面元素,在做ui自动化之前 ...

  5. LeetCode_104. Maximum Depth of Binary Tree

    104. Maximum Depth of Binary Tree Easy Given a binary tree, find its maximum depth. The maximum dept ...

  6. checkbox 在移动端显示为小圆圈问题

    在desktop显示正常,但是在移动端显示变为小圆圈,无法正确展示选中取消选中效果问题解决方案: display: block; width: 58px; height: 20px; -webkit- ...

  7. 【Leetcode_easy】830. Positions of Large Groups

    problem 830. Positions of Large Groups solution1: class Solution { public: vector<vector<int&g ...

  8. react中如何实现一个按钮的动态隐藏和显示(有效和失效)

    初始准备工作 constructor(props) { super(props); /* * 构建导出数据的初始参数,结合用户下拉选择后动态设置参数值 * */ this.state = { btnS ...

  9. 高级UI-DrawerLayout侧滑

    侧滑的方案有很多种,早期的开源SliddingMenu,以及后来的DrawerLayout以及NavigationView等都可实现侧滑效果,这里介绍的是DrawerLayout,下一节将介绍Navi ...

  10. cocos creator 判断滑动方向

    定义变量 public firstX = null; public firsty = null; 点击 获取坐标 this.viewNode.on(cc.Node.EventType.TOUCH_ST ...