codeforces 671D
首先O(n2)dp很好想
f[i][j]表示i子树内的所有边都被覆盖且i~j的路径也都被覆盖的最小花费。
考虑去掉无用的状态,其实真正用到的就是每一条链。
去掉第二维,f[i]表示i子树内的边都被覆盖且父向边也被覆盖的最小花费。
那么怎么转移呢?
f[i]可以是任意一条包含i和fa[i]的链转移而来,
首先要选这条链,还要加上这条链下端点到i所有其他儿子的f值,这样复杂度好像依旧很高
再优化,这不就是线段树取一个min吗?
那么我们现在要做的就是在每一个点上,在对应的一些链中取一个min
对于每条链,它是在它的下端点之上开始做出贡献的,
所以每个点控制的区间要是它的子树中所有向上连的边
当我们搞点x时,首先要算出他所有儿子的f值加和sum.然后要将以x为下端点的链的值更新为sum+c[i],还要将所有以x为上端点的链赋值inf,还要对其所有儿子的控制的链都加上sum-f[son],最后对于他控制的所有链取一个min就好了.
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 300005
#define inf 1000000000000000ll
#define LL long long
using namespace std;
int n,m,c[N];
int e=,head[N],out[N],in[N];
struct edge{int v,next;}ed[*N];
void add(int u,int v,int *h){
ed[e]=(edge){v,h[u]};
h[u]=e++;
}
int L[N],R[N],tot,d[N];
void dfs(int x,int fa){
L[x]=tot+;
for(int i=in[x];i;i=ed[i].next)
d[ed[i].v]=++tot;
for(int i=head[x];i;i=ed[i].next)
if(ed[i].v!=fa)dfs(ed[i].v,x);
R[x]=tot;
}
LL f[N];
LL minn[*N],lazy[*N];
void update(int rt,int l,int r,int x,LL y){
if(l==r){minn[rt]=y;return ;}
int mid=(l+r)>>;
if(x<=mid)update(rt<<,l,mid,x,y);
else update(rt<<|,mid+,r,x,y);
minn[rt]=min(min(minn[rt<<],minn[rt<<|])+lazy[rt],inf);
}
void add(int rt,int l,int r,int x,int y,LL z){
if(x<=l&&r<=y){lazy[rt]+=z;minn[rt]+=z;return ;}
int mid=(l+r)>>;
if(x<=mid) add(rt<<,l,mid,x,y,z);
if(y>mid) add(rt<<|,mid+,r,x,y,z);
minn[rt]=min(min(minn[rt<<],minn[rt<<|])+lazy[rt],inf);
}
LL query(int rt,int l,int r,int x,int y){
if(x<=l&&r<=y) return minn[rt];
LL ans=inf;
int mid=(l+r)>>;
if(x<=mid)ans=min(ans,query(rt<<,l,mid,x,y));
if(y>mid) ans=min(ans,query(rt<<|,mid+,r,x,y));
return min(ans+lazy[rt],inf);
}
void solve(int x,int fa){
LL ans=;
for(int i=head[x];i;i=ed[i].next){
if(ed[i].v==fa)continue;
solve(ed[i].v,x);
ans=min(f[ed[i].v]+ans,inf);
}
if(x==){f[]=ans;return;}
for(int i=in[x];i;i=ed[i].next)
update(,,m,d[ed[i].v],ans+c[ed[i].v]);
for(int i=out[x];i;i=ed[i].next)
update(,,m,d[ed[i].v],inf);
for(int i=head[x];i;i=ed[i].next){
if(ed[i].v==fa)continue;
add(,,m,L[ed[i].v],R[ed[i].v],ans-f[ed[i].v]);
}
f[x]=query(,,m,L[x],R[x]);
} int main(){
scanf("%d%d",&n,&m);
for(int i=,u,v;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v,head);
add(v,u,head);
}
for(int i=,u,v;i<=m;i++){
scanf("%d%d%d",&u,&v,&c[i]);
add(u,i,in);
add(v,i,out);
}
dfs(,);
memset(minn,0x15f,sizeof minn);
memset(lazy,,sizeof lazy);
solve(,);
if(f[]>=inf)printf("-1\n");
else printf("%lld\n",f[]);
return ;
}
youmu
codeforces 671D的更多相关文章
- Codeforces 671D Roads in Yusland [树形DP,线段树合并]
洛谷 Codeforces 这是一个非正解,被正解暴踩,但它还是过了. 思路 首先很容易想到DP. 设\(dp_{x,i}\)表示\(x\)子树全部被覆盖,而且向上恰好延伸到\(dep=i\)的位置, ...
- codeforces 671D Roads in Yusland & hdu 5293 Tree chain problem
dp dp优化 dfs序 线段树 算是一个套路.可以处理在树上取链的问题.
- Codeforces 671D. Roads in Yusland(树形DP+线段树)
调了半天居然还能是线段树写错了,药丸 这题大概是类似一个树形DP的东西.设$dp[i]$为修完i这棵子树的最小代价,假设当前点为$x$,但是转移的时候我们不知道子节点到底有没有一条越过$x$的路.如果 ...
- python爬虫学习(5) —— 扒一下codeforces题面
上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...
- 【Codeforces 738D】Sea Battle(贪心)
http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...
- 【Codeforces 738C】Road to Cinema
http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...
- 【Codeforces 738A】Interview with Oleg
http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...
- CodeForces - 662A Gambling Nim
http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...
- CodeForces - 274B Zero Tree
http://codeforces.com/problemset/problem/274/B 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...
随机推荐
- search a 2D matrix(在二维数组中搜索一个元素)
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the follo ...
- C语言关键字register、extern、static、一些总结,及项目中使用的心得
首先介绍两个概念: 一.变量的生存周期: 变量从建立到撤销的时间段成变量的生存周期.静态变量,从变量产生到整个程序执行结束.当函数使用变量结束后,变量的存储空间依然存在,变量的值也会随着函数的对其的使 ...
- Qt与FFmpeg联合开发指南(三)——编码(1):代码流程演示
前两讲演示了基本的解码流程和简单功能封装,今天我们开始学习编码.编码就是封装音视频流的过程,在整个编码教程中,我会首先在一个函数中演示完成的编码流程,再解释其中存在的问题.下一讲我们会将编码功能进行封 ...
- Python人工智能之-三大数学难点 !
1. 微积分: 定积分与不定积分.全微分.最小二乘法.二重积分.微分方程与差分方程等... 2. 线性代数: 行列式.矩阵.向量.线性方程组.矩阵的特性和特性向量.二次型等... 3. 概率论和统计学 ...
- ffmpeg 的 tbr tbc 和 tbn的意义
tbn = the time base in AVStream that has come from the container tbc = the time base in AVCodecConte ...
- No plugin found for prefix 'tomcat' in the current project and in the plugin groups和java.net.BindException: Address already in use: JVM_Bind <null>:8080的错误解决
错误报告:No plugin found for prefix 'tomcat' in the current project and in the plugin groups [org.apache ...
- 最优Django环境配置
2 最优Django环境配置 本章描述了我们认为对于中等和高级Django使用者来说最优的本地环境配置 2.1 统一使用相同的数据库引擎 一个常见的开发者错误是在本地开发环境中使用SQLite3,而在 ...
- pyCharm安装破解
补丁破解 下载 http://idea.lanyus.com/jar/JetbrainsCrack-2.7-release-str.jar 并将 JetbrainsCrack-2.7-release- ...
- ArcCore重构-Makefile模块化
基于官方arc-stable-9c57d86f66be,AUTOSAR版本3.1.5 基本问题 2. 编译系统中代码文件是否编译及目标文件集中定义在boards/board_common.mk,而 ...
- (ospf、rip、isis、EIGRP)常见的动态路由协议简介
路由器要转发数据必须先配置路由数据,通常根据网络规模的大小可设置静态路由或设置动态路由.静态路由配置方便,对系统要求低,适用于拓扑结构简单并且稳定的小型网络.缺点是不能自动适应网络拓扑的变化,需要人工 ...