CF767C Garland 【树形dp】By cellur925
2024-08-30 17:11:46
一句话题意:给定一个树,树有点权,要求把树的某些边删去,使树变成三个部分,每部分点权值和相等。
我们很容易想到,再读入的时候记录所有点的点权之和,点权除以3是最后权值相等的值。如果不能整除3一定无解,可以结束程序。
那么之后?
我们很自然地想到,状态可以设计为:f[i]为以i为根的子树上的点权和。边界为它自身点权(初值)。
转移也就很自然,f[i]=sigma f[j],j枚举i的儿子。但是很有可能儿子上的权值就满足最后的权值,我们就可以干掉这颗子树,继续遍历当前主树。最后两个断点就先从小子树中找到,再从较大子树中找到。
值得我们注意的是,这的确是一棵有根树,提链的老哥手里攥着的灯泡就是根,根是不能作为断点的。这点需要特别注意。
code
#include<cstdio>
#include<algorithm>
#include<vector> using namespace std; int n,sum,root;
int x=-,y=-;
int f[];
int val[];
vector<int>son[]; void TreeDp(int u,int fa)
{
f[u]=val[u];
for(int i=;i<son[u].size();i++)
{
int v=son[u][i];
if(v==fa) continue;
TreeDp(v,u);
if(f[v]==sum&&y==-) y=v;
else f[u]+=f[v];
}
if(f[u]==sum&&x!=root&&y!=-) x=u;
} int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
int u=,w=;
scanf("%d%d",&u,&w);
sum+=w;
if(u==) root=i;
val[i]=w;
son[u].push_back(i);
}
// printf("%d\n",sum);
if(sum%!=)
{
printf("-1");
return ;
}
sum/=;
TreeDp(root,-);
if(x!=-&&x!=root) printf("%d %d",x,y);
else printf("-1");
return ;
}
最新文章
- SQL SERVER 查看所有index
- U3D自定义Inspector项未触发保存事件的解决方案
- twitter bootstrap 2.x 3.x区别
- ios 中定时器:NSTimer, CADisplayLink, GCD
- 关于覆盖Object中的hashCode, equals和toString
- JForum2.1.9 安装过程
- Oracle用户密码过期和用户被锁解决方法【转】
- centos7.2部署最新ELK 5.3
- Java基础练习3(重载和重写)
- canvas实现随机验证码
- Android 屏幕适配插件 ScreenMatch
- 嵌入式linux内存越界定位和解决 (转)
- js 中编码(encode)和解码(decode)的三种方法
- 逆向 AWS API 设计
- Django学习手册 - 初识自定义分页
- Java关键字final、static使用总结(转)
- EBS-如何查看非自己提交的请求的结果
- STL 笔记(四) 迭代器 iterator
- Qt编译出错:“Cannot find file...... .pro.";
- 【转】 线段树完全版 ~by NotOnlySuccess
热门文章
- 学习日常笔记<;day13>;jsp加强
- Linux后台运行命令nohub输出pid到文件(转)
- 【.Net Core 学习系列】-- 自定义错误页面在IE浏览器中不能正常显示
- redis connetced refused remote
- linux上安装启动elasticsearch-5.5.1完整步骤
- centos 安装python2.7
- long类型字段转换成varchar2类型
- freemarker 模板
- Vs2012在Linux开发中的应用(5):项目属性的定义
- Android常见UI组件之ListView(二)——定制ListView