AT4995-[AGC034E] Complete Compress【树形dp】
正题
题目链接:https://www.luogu.com.cn/problem/AT4995
题目大意
\(n\)个点的一棵树,上面有一些棋子,每次可以选择两个棋子移动到他们之间的路径上相邻的点上,求最少多少步能移动到一个点上。
\(n\in[1,2000]\)
解题思路
如果固定最终节点的话,这个节点\(rt\)可行的话那么答案一定是\(\frac{\sum dis(rt,x)}{2}\)。
那么现在就转变为一个判定性问题,我们现在的操作变为了每次选择两个没有祖先关系的点,然后将它们往它们的\(LCA\)处移动一格。
同样的,我们发现如果我们在处理一个点\(x\)作为\(LCA\)时,我只会关心所有节点来自它的哪个儿子而不用考虑具体的位置。所以可以搞树形\(dp\)。
设\(f_x\)表示\(x\)的子树内最多的移动次数,定义\(s_x=\sum_{y\in subtree(x)}dis(x,y)\)的话,那么我们的转移和\(max\{s_y\}(x->y)\)有关。
若\(max\{s_y\}\times 2\leq s_x\),那么这里面的节点可以两两配对,\(f_x=\frac{s_x}{2}\)。
否则他\(s\)最大的子树\(y\)之中会有剩余的节点无法相互匹配,那么有$$f_x=s_x-s_y+min{f_y,s_y-\lfloor\frac{s_x}{2}\rfloor}$$
然后如果\(f_x=\frac{s_x}{2}\)那么\(x\)就是可行的答案
时间复杂度\(O(n^2)\)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2100;
struct node{
int to,next;
}a[N<<1];
int n,tot,ls[N],s[N],w[N],f[N],ans;
char v[N];
void addl(int x,int y){
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;return;
}
void dp(int x,int fa){
s[x]=w[x]=0;
int mx=0,son=0;
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(y==fa)continue;
dp(y,x);w[x]+=w[y];
s[x]+=s[y]+w[y];
if(s[y]+w[y]>mx)
mx=s[y]+w[y],son=y;
}
if(mx*2>s[x])
f[x]=s[x]-mx+min(f[son],mx-s[x]/2);
else f[x]=s[x]/2;
w[x]+=(v[x]=='1');
return;
}
int main()
{
scanf("%d",&n);
scanf("%s",v+1);
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
addl(x,y);addl(y,x);
}
ans=1e9;
for(int i=1;i<=n;i++){
dp(i,i);
if(s[i]&1)continue;
if(f[i]==s[i]/2)
ans=min(ans,f[i]);
}
if(ans==1e9)puts("-1");
else printf("%d\n",ans);
return 0;
}
AT4995-[AGC034E] Complete Compress【树形dp】的更多相关文章
- @atcoder - AGC034E@ Complete Compress
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个 N 个点的树,编号为 1, 2, ..., N.第 i ...
- 「AGC034E」 Complete Compress
「AGC034E」 Complete Compress 显然可以枚举根. 然后把某两棵棋子同时往深度浅的方向提,即对不存在祖先关系的两个棋子进行操作. 如果能到达那么就更新答案. 问题转化为如何判定能 ...
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
- COGS 2532. [HZOI 2016]树之美 树形dp
可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...
- 【BZOJ-4726】Sabota? 树形DP
4726: [POI2017]Sabota? Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 128 Solved ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- 树形DP
切题ing!!!!! HDU 2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...
- POJ2342 树形dp
原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...
随机推荐
- java线程池 面试题(精简)
什么是线程池? 线程池是一种多线程处理形式,处理过程中将任务提交到线程池,任务的执行交由线程池来管理. 如果每个请求都创建一个线程去处理,那么服务器的资源很快就会被耗尽,使用线程池可以减少创建和销毁线 ...
- 【java web】过滤器filter
一.过滤器简介 过滤器filter依赖于servlet容器 所谓过滤器顾名思义是用来过滤的,Java的过滤器能够为我们提供系统级别的过滤,也就是说,能过滤所有的web请求, 这一点,是拦截器无法做到的 ...
- Mybatis中多表联查,查询出来的字段出现重名,造成数据异常的解决方法!
在做一对多出现的问题,引发的思考:当数据库表中,主表的主键id和明细表的中的字段名相同时怎么办?Mybatis进行自动映射赋值的时候会不会出现异常? 注意:M ...
- linux 常用命令(五)——(centos7-centos6.8)JDK安装
1.安装jdk前先检测系统是否带有OpenJDK:若存在则删除 查看: java -version 查询出OpenJDK相关的文件:rpm -qa | grep java 删除OpenJDK相关的文件 ...
- 安全强化机制——SELinux
1.基本 SELINUX 安全性概念 SELINUX(Security Enhanced Linux),意思是安全增强型Linux, 是可保护你系统安全性的额外机制 在某种程度上 , 它可以被看作是与 ...
- 在python3.6环境下使用cxfreeze打包程序
在python3.6环境下使用cxfreeze打包程序 环境:python3.6 打包程序:aliens_invasion 原本想使用pyintaller 进行打包,使用pip的安装过程也没有问题,打 ...
- android kotlin 子线程中调用界面UI组件崩溃
UI 只能在主线程内更新,子线程需要更新UI组件时可以这样: fun fuck(){ Executors.newSingleThreadExecutor().execute{ // url reque ...
- Shell脚本一键部署——源码编译安装MySQL及自动补全工具
Shell脚本一键部署--源码编译安装MySQL及自动补全工具 编译安装MySQL 1.软件包 Mysql安装包 将安装包拖至/opt目录下,编辑一个脚本文件,将以下内容复制进去,然后source或者 ...
- noip模拟32
\(\color{white}{\mathbb{山高而青云冷,池深而蛟穴昏,行以慎步,援以轻身,名之以:落石}}\) 开题发现 \(t1\) 80分特别好写,于是先写了 但是这个做法没有任何扩展性,导 ...
- 使用AOP+自定义注解完成spring boot的接口权限校验
记使用AOP+自定义注解完成接口的权限校验,代码如下: pom文件添加所需依赖: 1 <dependency> 2 <groupId>org.aspectj</group ...