题目

【问题描述】

小迟生活的城市是⼀棵树(树指的是⼀个含有 \(n\) 个节点以及 \(n-1\) 条边的⽆向连通图),节点编号从 \(1\) 到 \(n\),每条边拥有⼀个权值 \(value\),表示通过这条边的时候你需要交纳的金钱(注意,有可能这个值为负数,也就是说你经过这条边的时候你可以赚钱)

小迟是⼀个杰出的马路工,他居住在节点 \(s\),他能够选择任意⼀个节点 \(m\),并将从节点 \(s\) 到节点 \(m\) 的简单路径(简单路径指的是不经过同⼀个节点两次)上的所有边的权值都修改为 \(0\).

现在小迟获得 \(q\) 个请求,每个请求都是以 \(a\) \(b\) 的形式给出,表示小迟的好朋友小早希望从节点 \(a\) 走简单路径到节点$ b$,小迟希望能最小化小早需要缴纳的钱。

需要注意的是,小迟获得的这 \(q\) 个请求是相互独立的,也就是说您只需要对于每⼀个请求,决定小迟的⼀个修路⽅案,使得小早需要缴纳的钱尽可能的少。

【输入格式】

输⼊⽂件名为 \(road.in\)。

第⼀行三个正整数为 \(n,q,s\)。

接下来 \(n-1\) 行,每行三个整数$ x$ \(y\) \(z\), 表示有⼀条边 \((x,y)\),\(value\) 为$ z$。

接下来 \(q\) 行,每行两个正整数 \(a\) \(b\),表示请求。

【输出格式】

输出⽂件名为 \(road.out\)。

\(q\) 行,每行⼀个整数,表示需要缴纳的最少的钱。

【样例输入】

3 2 1
1 2 1
2 3 1
1 2
1 3

【样例输出】

0
0

【样例解释】

对于第⼀次询问 \(1\) \(2\), ⼩迟可以修从 \(1\) 到 \(2\) 的路,从⽽使得⼩早不需要缴纳⾦钱;

对于第⼆次询问 \(1\) \(3\), ⼩迟可以修从 \(1\) 到 \(3\) 的路,从⽽使得⼩早不需要缴纳⾦钱。

【数据规模及约定】

对于 \(30\%\)的数据,\(n≤1000,q≤1000\).

对于 \(100\%\)的数据,\(1≤n,q≤200000,1≤x,y≤n,|z|≤1000\).

解法

首先考虑没有负权边的情况,显然只需要树链剖分维护,线段树维护区间和,回答询问时选取将两端点到\(s\)点的路径中,点权和较大的那一条修改为\(0\)权值即可.

然后考虑有负权边的情况.

我们可以以\(s\)为根节点建树,将每个点的权值设置为它到根节点的距离,记\(x\)为\(u \rightarrow v\)简单路径中点权最大的点,显然将\(s \rightarrow x\)路径中边设为\(0\)权值是最佳方案.要求这个最佳方案的缴纳钱数,需要用到\(LCA\).一个特殊情况是,如果\(x\)的权值为负,那么不删除为最佳方案.

综上,答案为

\[weight[u]+weight[v]-2*weight[x]-max(f(u,v)-weight[x],0
\]

其中\(f(u,v)\)表示\(u \rightarrow v\)简单路径中点权最大的点的点权.

代码

#include<cstdio>
#include<algorithm>
using namespace std;
const int SIZE=500005;
const int INF=0x3F3F3F3F; int n,q,s;
int weight[SIZE],weightx[SIZE],siz[SIZE],son[SIZE],dep[SIZE],Fa[SIZE],ID[SIZE],top[SIZE]; struct Tree
{
int L,R;
int sum,tag;
#define L(v) T[v].L
#define R(v) T[v].R
#define sum(v) T[v].sum
#define tag(v) T[v].tag
#define LC(v) (v*2)
#define RC(v) (v*2+1)
#define pushup(v) sum(v)=max(sum(LC(v)),sum(RC(v)))
}T[SIZE*4];
void Build(int p,int L,int R)
{
L(p)=L;R(p)=R;
if(L==R){sum(p)=weightx[L];return;}
int Mid=(L+R)>>1;
Build(LC(p),L,Mid);
Build(RC(p),Mid+1,R);
pushup(p);
} int query(int p,int L,int R)
{
if(L>R(p)||R<L(p))return -INF;
if(L<=L(p)&&R>=R(p))return sum(p);
return max(query(LC(p),L,R),query(RC(p),L,R));
} int head[SIZE],nex[SIZE],ver[SIZE],edge[SIZE],Tot=1;
void ins(int u,int v,int e){ nex[++Tot]=head[u]; head[u]=Tot; ver[Tot]=v; edge[Tot]=e; } void DFS1(int u,int Dis)
{
siz[u]=1;
weight[u]=Dis;
for(int i=head[u];i;i=nex[i])
{
int v=ver[i];
if(dep[v])continue;
dep[v]=dep[u]+1;
Fa[v]=u;
DFS1(v,Dis+edge[i]);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
} int Cnt=0;
void DFS2(int u,int TOP)
{
ID[u]=++Cnt;
weightx[Cnt]=weight[u];
top[u]=TOP;
if(siz[u]==1)return;
DFS2(son[u],TOP);
for(int i=head[u];i;i=nex[i])
{
int v=ver[i];
if(v==Fa[u]||v==son[u])continue;
DFS2(v,v);
}
} int f(int u,int v)
{
int Res=-INF;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])swap(u,v);
Res=max(Res,query(1,ID[top[u]],ID[u]));
u=Fa[top[u]];
}
if(dep[u]<dep[v])swap(u,v);
Res=max(Res,query(1,ID[v],ID[u]));
return Res;
} int LCA(int u,int v)
{
while(top[u]!=top[v])
dep[top[u]]<dep[top[v]]? v=Fa[top[v]] : u=Fa[top[u]];
return dep[u]<dep[v]? u : v;
} int main()
{
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
scanf("%d%d%d",&n,&q,&s);
int u,v,e;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&e);
ins(u,v,e);
ins(v,u,e);
}
dep[s]=s;
DFS1(s,0);
DFS2(s,s);
Build(1,1,n);
while(q--)
{
scanf("%d%d",&u,&v);
int x=LCA(u,v);
printf("%d\n",weight[u]+weight[v]-2*weight[x]-max(f(u,v)-weight[x],0));
}
return 0;
}

马路 树链剖分/线段树/最近公共祖先(LCA)的更多相关文章

  1. jzoj4918. 【GDOI2017模拟12.9】最近公共祖先 (树链剖分+线段树)

    题面 题解 首先,点变黑的过程是不可逆的,黑化了就再也洗不白了 其次,对于\(v\)的祖先\(rt\),\(rt\)能用来更新答案当且仅当\(sz_{rt}>sz_{x}\),其中\(sz\)表 ...

  2. 【bzoj3626】[LNOI2014]LCA 树链剖分+线段树

    题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...

  3. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  4. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  5. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  6. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  7. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  8. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  9. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  10. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

随机推荐

  1. Hyperparameter tuning

    超参数调整 详细可以参考官方文档 定义 在拟合模型之前需要定义好的参数 适用 Linear regression: Choosing parameters Ridge/lasso regression ...

  2. windows密码抓取工具-mimikatz

    前言 介绍一下windows的密码hash值的组成: Windows系统下的hash密码格式为:用户名称:RID:LM-HASH值:NT-HASH值,例如: Administrator::C8825D ...

  3. python django项目的搭建及初始配置

    1.创建项目并创建应用 django-admin startproject my_project # 创建项目python manage.py startapp my_app # 创建应用 1.1 项 ...

  4. 3级搭建类301-Oracle 11g RAC 双节点搭建(11.2.0.4)非公

    项目文档引子系列是根据项目原型,制作的测试实验文档,目的是为了提升项目过程中的实际动手能力,打造精品文档AskScuti. 项目文档引子系列目前不对外发布,仅作为博客记录.如学员在实际工作过程中需提前 ...

  5. Vue.js_devtools_5.1.0.zip【需要的可自行下载】

    点击链接下载: Vue.js_devtools_5.1.0.zip

  6. Python之四:控制流

    1.If 逻辑判断: if a: b elif c: d else: e 先判断a语句块的值是否为真,如果为真,则执行b语句块,如果不为真则转到elif判断c语句块的值是否为真,如果为真执行d语句块, ...

  7. oracle建数据库

    oracle用户界面登陆 用户要切换到oracle sqlplus / as sysdba //sys用户是oracle的最高管理员所以要加上as help index //查看命令列表,sql中不区 ...

  8. 手把手带你开发一款 IIS 模块后门

    https://cloud.tencent.com/developer/article/1507913 首先准备工具 VS2017 IIS 开始开发 先打开 VS 创建一个 winfrom 项目然后添 ...

  9. BZOJ4710: [Jsoi2011]分特产 组合数学 容斥原理

    题意:把M堆特产分给N个同学,要求每个同学至少分到一种特产,共有多少种分法? 把A个球分给B个人的分法种数:(插板法,假设A个球互不相同,依次插入,然后除以全排列去重) C(A,B+A) 把M堆特产分 ...

  10. nginx配置从远程获取静态资源

    前置条件:现有两台内网互通机器192.168.0.100.192.168.0.101,其中192.168.0.100可以通过外网网络.业务需求:需要通过外网访问处于192.168.0.101机器上的静 ...