一句话题意:给定一个树,树有点权,要求把树的某些边删去,使树变成三个部分,每部分点权值和相等。

我们很容易想到,再读入的时候记录所有点的点权之和,点权除以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 ;
}

最新文章

  1. SQL SERVER 查看所有index
  2. U3D自定义Inspector项未触发保存事件的解决方案
  3. twitter bootstrap 2.x 3.x区别
  4. ios 中定时器:NSTimer, CADisplayLink, GCD
  5. 关于覆盖Object中的hashCode, equals和toString
  6. JForum2.1.9 安装过程
  7. Oracle用户密码过期和用户被锁解决方法【转】
  8. centos7.2部署最新ELK 5.3
  9. Java基础练习3(重载和重写)
  10. canvas实现随机验证码
  11. Android 屏幕适配插件 ScreenMatch
  12. 嵌入式linux内存越界定位和解决 (转)
  13. js 中编码(encode)和解码(decode)的三种方法
  14. 逆向 AWS API 设计
  15. Django学习手册 - 初识自定义分页
  16. Java关键字final、static使用总结(转)
  17. EBS-如何查看非自己提交的请求的结果
  18. STL 笔记(四) 迭代器 iterator
  19. Qt编译出错:“Cannot find file...... .pro.&quot;
  20. 【转】 线段树完全版 ~by NotOnlySuccess

热门文章

  1. 学习日常笔记&lt;day13&gt;jsp加强
  2. Linux后台运行命令nohub输出pid到文件(转)
  3. 【.Net Core 学习系列】-- 自定义错误页面在IE浏览器中不能正常显示
  4. redis connetced refused remote
  5. linux上安装启动elasticsearch-5.5.1完整步骤
  6. centos 安装python2.7
  7. long类型字段转换成varchar2类型
  8. freemarker 模板
  9. Vs2012在Linux开发中的应用(5):项目属性的定义
  10. Android常见UI组件之ListView(二)——定制ListView