【CF767C】Garland
2024-08-22 18:20:42
分析:
这个题我是看着翻译做的,感觉不是很难,很普通的一个树形dp
题目大意:
在一棵树上分离出三个子树,使这三个子树的点权和相等。
明确题目意思这个题就简单多了吧。
我们会发现每一棵子树的点权是固定的,因为点权总和固定,设每一部分的大小为W,那么我们就从下往上更新(因为树形dp的基本做法就是从下向上更新,用儿子更新爸爸),遇到等于W的子树就切一刀,sz重置成0,这就可以一边遍历子树,一边算sz.
剪枝(额。。好像不能叫剪枝)也挺容易想,如果点权总和不是3的倍数,那么肯定不行(分不出三个相等)
这题细节挺多的,需要注意一条链的情况和和是三的倍数但不能分成几个相等的部分的情况。
最后的那个地方cnt >= 3就是想,如果分成了大于等于3个子树,就直接输出两个就行了,否则的话就输出-1,证明我们最多只能找到两个子树权值是整棵树的 1/3
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = ; inline int read(){
char ch = getchar();
int f = , x = ;
while(ch > '' || ch < ''){if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
} int w[maxn],x,y;
int head[maxn],tot;
struct Edge{
int from,to,val,next;
}edge[maxn<<];
int n,root,sum,sz[maxn],cnt,ans[]; void add(int u,int v){
edge[++tot].from = u;
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot;
} int dfs(int x,int fa){
sz[x] = w[x];
for(int i=head[x];i;i=edge[i].next){
int v = edge[i].to;
if(v != fa){
dfs(v , x);
sz[x] += sz[v];
}
}
if(sz[x] == sum){
ans[++cnt] = x;
sz[x] = ;
}
} int main(){
n = read();
for(int i=;i<=n;i++){
x = read(); y = read();
if(x != ) add(i , x), add(x , i);
else root = i;
w[i] = y;
sum += y;
}
if(sum % != ) printf("-1\n");
else {
sum /= ;
dfs(root , );
if(cnt >= ) printf("%d %d\n",ans[],ans[]);
else printf("-1\n");
}
return ;
}
最新文章
- 自适应备忘录 demo
- debian清除无用的库文件(清理系统,洁癖专用)
- 使用imp加载python模块
- linux svn服务器搭建、客户端操作、备份与恢复
- Python按行读取文件
- html跳转到同一个页面的不同位置
- innerHTML在IE中报错
- 对于IE6及以下版本的处
- android两种方式获取AsyncTask返回值
- 直接拿来用!最火的iOS开源项目(一)
- Python用Pillow(PIL)进行简单的图像操作
- windows系统下安装node
- Android基础字符串String.md
- 最近面试 Java 后端开发的感受!
- javaweb中上传图片并显示图片,用我要上传课程信息(里面包括照片)这个例子说明
- 改变Tomcat在地址栏上显示的小猫图标
- Ionic3.0 输入状态时隐藏Tabs栏
- 深入理解JVM虚拟机:(一)Java运行时数据区域
- dubbo超时优先级设置
- Silverlight中图片显示