首先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的更多相关文章

  1. Codeforces 671D Roads in Yusland [树形DP,线段树合并]

    洛谷 Codeforces 这是一个非正解,被正解暴踩,但它还是过了. 思路 首先很容易想到DP. 设\(dp_{x,i}\)表示\(x\)子树全部被覆盖,而且向上恰好延伸到\(dep=i\)的位置, ...

  2. codeforces 671D Roads in Yusland & hdu 5293 Tree chain problem

    dp dp优化 dfs序 线段树 算是一个套路.可以处理在树上取链的问题.

  3. Codeforces 671D. Roads in Yusland(树形DP+线段树)

    调了半天居然还能是线段树写错了,药丸 这题大概是类似一个树形DP的东西.设$dp[i]$为修完i这棵子树的最小代价,假设当前点为$x$,但是转移的时候我们不知道子节点到底有没有一条越过$x$的路.如果 ...

  4. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  5. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  6. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  7. 【Codeforces 738A】Interview with Oleg

    http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...

  8. CodeForces - 662A Gambling Nim

    http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...

  9. CodeForces - 274B Zero Tree

    http://codeforces.com/problemset/problem/274/B 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...

随机推荐

  1. Numpy快速入门——shape属性,你秒懂了吗

    前言 对于学习NumPy(Numeric Python),首先得明确一点是:Numpy 是用来处理矩阵数组的. shape 属性 对于shape函数,官方文档是这么说明: the dimensions ...

  2. leetcode刷题指南

    转载自:http://blog.csdn.net/lnho2015/article/details/50962989 以下是我个人做题过程中的一些体会: 1. LeetCode的题库越来越大,截止到目 ...

  3. PLSQL学习教程(全)

    基于ORACLE9i+PL/SQLDeveloper7.1.4) 课程 一 PL/SQL 基本查询与排序 本课重点: 1.写SELECT语句进行数据库查询 2.进行数学运算 3.处理空值 4.使用别名 ...

  4. SQL 经典语句

    15题需要再分析.没弄懂 使用scott/tiger用户下的emp表和dept表完成下列练习, 表的结构说明如下 emp员工表(empno员工号/ename员工姓名/job工作/mgr上级编号/hir ...

  5. 转发 JBPM工作流小结

    JBoss 题记:某部门领导有天突发奇想,把我们几个人叫过去,曰:最近出去开会,老有人推销自己的工作流产品,说的这好那好,你们几个给我研究研究.正好刚做完的xxx子系统里有一个申请审批的流程,你们按这 ...

  6. Kinect 骨骼追踪数据的处理方法

    http://www.ituring.com.cn/article/196144 作者/ 吴国斌 博士,PMP,微软亚洲研究院学术合作经理.负责中国高校及科研机构Kinect for Windows学 ...

  7. SQLServer2PostgreSQL迁移过程中的几个问题

    1.PostgreSQL 跨平台迁移工具Migration Toolkit的使用指南:http://www.enterprisedb.com/docs/en/8.4/mtkguide/Table%20 ...

  8. esp-12e折腾

    寒假前就从x宝买了esp-12e以及esp32s,当时似乎是想给自己的蓝牙开门升级换代?esp32s拿来过度linux? 寒假放在书包拿回去以为有时间会玩玩,没想到一直耽搁到现在.前两天才拿出来,网上 ...

  9. kaggle入门项目:Titanic存亡预测 (一)比赛简介

    自从入了数据挖掘的坑,就在不停的看视频刷书,但是总觉得实在太过抽象,在结束了coursera上Andrew Ng 教授的机器学习课程还有刷完一整本集体智慧编程后更加迷茫了,所以需要一个实践项目来扎实之 ...

  10. Stack和Vector源码分析

    Stack和Vector源码分析 Stack和Vector源码分析stack源码分析1.Stack是什么2.Stack的结构图3.Stack继承关系4.Stack的主要方法5.Stack源码Vecto ...