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个人去 ,根据题意我们可以很容易的得到如下递推公式 ...
随机推荐
- C语言 Ubuntu系统 UTF-8 文字处理
关于UTF-8的规则:https://baike.baidu.com/item/UTF-8/481798?fr=aladdin 使用windows系统下的Ubuntu子系统,实现C语言对UTF-8编码 ...
- .Net Core 配置系统解析
特性 支持多种格式 xml json ini memory command env 支持多层嵌套 //.Net Core { "username": "Jack" ...
- JAVA虚拟机中的堆内存Heap与栈内存Stack
原文链接:http://www.cnblogs.com/laoyangHJ/archive/2011/08/17/gc-Stack.html 深入Java虚拟机:JVM中的Stack和Heap 在JV ...
- 在PyQt中构建 Python 菜单栏、菜单和工具栏
摘要:菜单.工具栏和状态栏是大多数GUI 应用程序的常见且重要的图形组件.您可以使用它们为您的用户提供一种快速访问应用程序选项和功能的方法. 本文分享自华为云社区<Python 和 PyQt:创 ...
- vmware 配置不同网段双网卡。
一.前言 需求:由于LVS演练需要,需要配置两张linux OS网卡,而且是不同网段. 准备: 物理机:单网卡 VMware:centos 6.8 二.配置 第一步:新建虚拟机VMware,cento ...
- docker搭建mysql集群
目录 一.集群方案 二.安装PXC集群 三.Haproxy负载均衡 四.访问测试 五.节点宕机或重启 六.参考 一.集群方案 1.Replication 速度快,但仅能保证弱一致性,适用于保存价值不高 ...
- RabitMq过期时间TTL
第一种:给消息设置过期时间 启动一个插件 @Bean public DirectExchange DirectExchange() { return new DirectExchange(" ...
- SpringBoot笔记(5)
一.Web原生组件注入 1.使用Servlet API @ServletComponentScan(basePackages = "com.atguigu.admin") :指定原 ...
- JVM(一)类加载器与类加载过程
JVM是面试必面的一个知识点,也是高级程序员必备的一个技能.以下是JVM整体核心内容,包括类加载系统,运行时数据区内部结构,执行引擎,本地方法接口. 首先来学习类的加载器,虚拟机把描述类的数据从Cla ...
- 使用Mosquitto实现MQTT客服端C语言
上一篇文章已经将mosquitto移植到了arm平台上,现在将使用mosquitto完成mqtt客服端的demo,了解过mqtt协议的小伙伴都知道,mqtt主要分为代理服务器.发布者.订阅者三部分 ...