Codeforces 1000G Two-Paths 树形动态规划 LCA
原文链接https://www.cnblogs.com/zhouzhendong/p/9246484.html
题目传送门 - Codeforces 1000G Two-Paths
题意
给定一棵有 $n(2\leq n\leq 3\times 10^5)$ 个节点的树,其中节点 $i$ 有权值 $a_i$,边 $e$ 有权值 $w_e$。$(1\leq a_i,w_e\leq 10^9)$
现在给出 $q(1\leq q\leq 4\times 10^5)$ 组询问,每组询问给定两个数 $x,y(1\leq x,y\leq n)$。
如果一条路径的起点和终点分别为 $x$ 和 $y$,而且这条路径重复经过同一条边最多 $2$ 次(点可以多次经过),那么这条路径合法。
一条合法路径 $P$ 的价值为 $Pr(p)$。$\text{Pr}(p) = \sum\limits_{v \in \text{distinct vertices in } p}{a_v} - \sum\limits_{e \in \text{distinct edges in } p}{k_e \cdot w_e}$。
其中 $k_e$ 为路径 $p$ 经过 $e$ 的次数。
每次询问问所有合法路径的最大价值。
题解
我们来跑一下树形dp。
求出以下值。(下面是示意图,有填色的部分表示被计算)
其中 $dp1,dp2,f1,sum$ 都表示所取的部分的合法最大值。





再描述一下上面六个量的意义:
dp1[x]:往 $x$ 的后代节点走最多可以赚多少。
dp2[x]:往 $x$ 的祖先走最多可以赚多少。
f1[x]:从 $x$ 的祖先向 $x$ 走最多可以赚多少。
sum[x]:令树根到 $x$ 父亲的链为主链,假设主链上行走没有任何消耗和获益,向主链走最多可以获益多少。
len[x]:$x$ 到根的距离(带边权)。
s[x]:$x$ 的深度。
在回答询问 $x,y$ 的时候,首先从 $x$ 到 $y$ 的路径一定被选,其中的边一定只走一次。
其他的我们根据之前维护的量分类讨论加加减减一下就可以了。
详见代码。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=300005,M=N*2;
LL read(){
LL x=0;
char ch=getchar();
while (!('0'<=ch&&ch<='9'))
ch=getchar();
while ('0'<=ch&&ch<='9')
x=x*10+ch-48,ch=getchar();
return x;
}
struct Gragh{
int cnt,y[M],nxt[M],fst[N];
LL z[M];
void clear(){
cnt=0;
memset(fst,0,sizeof fst);
}
void add(int a,int b,LL c){
y[++cnt]=b,z[cnt]=c,nxt[cnt]=fst[a],fst[a]=cnt;
}
}g;
int n,q,fa[N][20],depth[N],xx,yy;
LL a[N],dp1[N],f1[N],dp2[N],sum[N],fadis[N],len[N],s[N];
void dfs1(int x,int pre,int d,LL L){
fa[x][0]=pre;
depth[x]=d;
len[x]=L;
s[x]=s[pre]+a[x];
for (int i=1;i<20;i++)
fa[x][i]=fa[fa[x][i-1]][i-1];
dp1[x]=0;
for (int i=g.fst[x];i;i=g.nxt[i]){
int y=g.y[i];
LL z=g.z[i];
if (y!=pre){
dfs1(y,x,d+1,L+z);
fadis[y]=z;
f1[y]=max(dp1[y]+a[y]-z*2,0LL);
dp1[x]+=f1[y];
}
}
}
void dfs2(int x,int pre,LL v,LL v2){
dp2[x]=v;
sum[x]=v2;
for (int i=g.fst[x];i;i=g.nxt[i]){
int y=g.y[i];
LL z=g.z[i];
if (y!=pre){
LL _v=max(v+a[x]+dp1[x]-f1[y]-2*z,0LL);
LL _v2=max(v2+dp1[x]-f1[y],0LL);
dfs2(y,x,_v,_v2);
}
}
}
int LCA(int x,int y){
if (depth[x]<depth[y])
swap(x,y);
for (int i=19;i>=0;i--)
if (depth[x]-(1<<i)>=depth[y])
x=fa[x][i];
if (x==y)
return x;
for (int i=19;i>=0;i--)
if (fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
xx=x,yy=y;
return fa[x][0];
}
int main(){
scanf("%d%d",&n,&q);
for (int i=1;i<=n;i++)
a[i]=read();
g.clear();
for (int i=1;i<n;i++){
int a=read(),b=read();
LL c=read();
g.add(a,b,c);
g.add(b,a,c);
}
dfs1(1,0,0,0);
dfs2(1,0,0,0);
while (q--){
int x,y,lca;
scanf("%d%d",&x,&y);
if (depth[x]>depth[y])
swap(x,y);
lca=LCA(x,y);
if (x==lca){
if (y==lca){
printf("%I64d\n",dp1[x]+dp2[x]+a[x]);
continue;
}
LL ans=s[y]-s[x]+a[x];
ans-=len[y]-len[x];
ans+=sum[y]-sum[x];
ans+=dp2[x]+dp1[y];
printf("%I64d\n",ans);
continue;
}
LL ans=s[x]+s[y]-s[lca]*2+a[lca];
ans-=len[x]+len[y]-len[lca]*2;
ans+=sum[x]+sum[y]-sum[xx]-sum[yy];
ans+=dp1[lca]-f1[xx]-f1[yy];
ans+=dp2[lca]+dp1[x]+dp1[y];
printf("%I64d\n",ans);
}
return 0;
}
Codeforces 1000G Two-Paths 树形动态规划 LCA的更多相关文章
- 蓝桥杯 ALGO-4 结点选择 (树形动态规划)
问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值.如果一个点被选择了,那么在树上和它相邻的点都不能被选择.求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n . 接下来的 ...
- 树形动态规划(树状DP)小结
树状动态规划定义 之所以这样命名树规,是因为树形DP的这一特殊性:没有环,dfs是不会重复,而且具有明显而又严格的层数关系.利用这一特性,我们可以很清晰地根据题目写出一个在树(型结构)上的记忆化搜索的 ...
- Codeforces 581F Zublicanes and Mumocrates - 树形动态规划
It's election time in Berland. The favorites are of course parties of zublicanes and mumocrates. The ...
- Codeforces Beta Round #14 (Div. 2) D. Two Paths 树形dp
D. Two Paths 题目连接: http://codeforces.com/contest/14/problem/D Description As you know, Bob's brother ...
- Codeforces 839C Journey - 树形动态规划 - 数学期望
There are n cities and n - 1 roads in the Seven Kingdoms, each road connects two cities and we can r ...
- Codeforces Round #343 (Div. 2) E. Famil Door and Roads (树形dp,lca)
Famil Door's City map looks like a tree (undirected connected acyclic graph) so other people call it ...
- LEETCODE —— Unique Paths II [动态规划 Dynamic Programming]
唯一路径问题II Unique Paths II Follow up for "Unique Paths": Now consider if some obstacles are ...
- Codeforces Gym 100015C City Driving 离线LCA
City Driving 题目连接: http://codeforces.com/gym/100015/attachments Description You recently started fre ...
- 【ACM/ICPC2013】树形动态规划专题
前言:按照计划,昨天应该是完成树形DP7题和二分图.最大流基础专题,但是由于我智商实在拙计,一直在理解树形DP的思想,所以第二个专题只能顺延到今天了.但是昨天把树形DP弄了个5成懂我是很高兴的!下面我 ...
随机推荐
- python学习第6天
id is == 代码块 代码块的缓存机制 小数据池(不同代码块的缓存机制) 小数据池(驻留机制)总结 数据类型之间的转换 int bool str 三者转化是可以的. bool 可以与所有的数据类 ...
- 前端 ----关于DOM的事件操作
关于DOM的事件操作 一.JavaScript的组成 JavaScript基础分为三个部分: ECMAScript:JavaScript的语法标准.包括变量.表达式.运算符.函数.if语句.for ...
- 行为驱动:BDD框架之Cucumber初探
1.cucumber cucumber早在ruby环境下应用广泛,作为BDD框架的先驱,cucumber后来被移植到了多平台,简单来说cucumber是一个测试框架,就像是juint或是rspec一样 ...
- [记录]一个有趣的url请求(nodejs)
1 前言 IDE是webstrom,跟项目编程语言,应该没有多大关系. 2 现象 两个看起来是一样的url,但是一个能访问一个不能访问. 然后,复制url到console中发现了差异,分别是:file ...
- Spring Cloud构建微服务架构(五)服务网关
通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了.比如下图所示: 我们使用Spring Cloud Netflix中的Eureka实现了服务 ...
- 使用PHP Manager for IIS时,Windws 10自带IIS注意事项
1)开启IIS 10:在“控制面板”的“程序和功能”的“启用或关闭Windows功能”内,勾选(启用)“Internet Information Services”,然后确定,进行安装. 2)若要使用 ...
- winform数据存储的方式
存储的方式有三种: 一.SQL数据库 二.Access(office 2007版本以上是需要安装驱动的) 三.XML
- 安装python的pip模块
安装python的pip模块 网址https://pypi.python.org/pypi/pip 选择,点击下载 将文件解压到C:\Users\Administrator\AppData\Local ...
- C语言学习及应用笔记之二:C语言static关键字及其使用
C语言有很多关键字,大多关键字使用起来是很明确的,但有一些关键字却要相对复杂一些.我们这里要说明的static关键字就是如此,它的功能很强大,相应的使用也就更复杂. 一般来说static关键字的常见用 ...
- java 中int与integer的区别
int与integer的区别从大的方面来说就是基本数据类型与其包装类的区别: int 是基本类型,直接存数值,而integer是对象,用一个引用指向这个对象 1.Java 中的数据类型分为基本数据类型 ...