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 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...
随机推荐
- JVM学习--(六)类加载器原理
我们知道我们编写的java代码,会经过编译器编译成字节码文件(class文件),再把字节码文件装载到JVM中,映射到各个内存区域中,我们的程序就可以在内存中运行了.那么字节码文件是怎样装载到JVM中的 ...
- JAVA设计模式--学习总结(序)
设计模式(Design pattern)是一套被反复使用的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 常见的设计模式有23种.分为三大类:创建型模式, ...
- currval of sequence "follow_id_seq" is not yet defined in this session
postgresql上使用 select currval('follow_id_seq'); 报错: currval of sequence "follow_id_seq" is ...
- Scala编程入门---函数式编程之集合操作
集合的函数式编程: 实战常用: //map案例实战:为List中的每个元素都添加一个前缀. List("leo","Jen","peter" ...
- Oracle基础快速入门
数据库体系结构 物理存储结构与Oracle启动时关系是 依次打开 参数(startup nomount).控制(startup mount).数据文件(open) 物理存储结构:指实际的文件存储形式 ...
- C# 数据库链接字符串加密工具
有些项目尤其是WinForm或者是WPF项目,针对一些工具形式的小项目,不想软件流出去之后,懂程序的的拿到手之后一看配置文件就知道了我们数据库的用户名和密码,如果外网能访问的话,那就麻烦大了.所以这里 ...
- 【转】javascript 浮点数运算问题
大多数语言在处理浮点数的时候都会遇到精度问题,但是在JS里似乎特别严重,来看一个例子 alert(45.6*13); 结果居然是592.800000000001,当然加法之类的也会有这个问题 那这是j ...
- 0513JS数组内置方法、数学函数、时间函数
|数组中常用的内置方法|-push()与pop()|--push()是往数组的尾部添加,同时返回新数组的长度 var attr = [1,2,3,4,5];var attr2 = [6,7,8,9,0 ...
- .net Core 微服务框架 surging 使用
surging 是一个分布式微服务框架,提供高性能RPC远程服务调用,采用Zookeeper.Consul作为surging服务的注册中心, 集成了哈希,随机,轮询作为负载均衡的算法,RPC集成采用的 ...
- CF#483(div2 C)
http://codeforces.com/contest/984/problem/C C. Finite or not time limit per test 1 second memory lim ...