AtCoder Grant Contest 010 C - Cleaning dfs+逻辑+dp思想
来源:互联网 发布:java防止重复提交 编辑:程序博客网 时间:2024/04/30 08:21
题意:给定一棵树,每个节点的权值为Ai,每次可以挑选两个叶子节点,将两个叶子节点之间路径上的权值-1。问最后能不能使得整棵树的权值为0。
解法:验证解的存在性,就去试着找出一组可行解。这题从最末端的情况开始想就可以很容易想出dp。
随便找个非叶子节点,将其作为整棵树的根,现在对这个有根树进行分析。
首先可以将路径进行归类,对于一个非叶子节点A,经过其的路径可以分为两种情况:
1.经过一个子节点;
2.经过两个子节点。
路径经过两个子节点意味着这条路不用往上走了,即不会影响A的父亲。
路径经过一个子节点意味着需要再向上传递,因为另一个端点不在以A为根的子树里。
接着构思dfs的细节:
1.考虑叶子节点,叶子节点的权值一定得向上传递,因为叶子节点是路径的端点。
2.考虑非叶子节点A‘,已知权值是Ai,设从其儿子节点需要传上来的权值和是tot,其中第一种边贡献了x1,第二种边贡献了x2,其中,x1需要向上传递。容易列出方程:
x1+x2=Ai,2*x2+x1=tot,可以解出x1与x2的值。
接着要做的就是判断x1与x2的合法性:
1.x1与x2均要大于等于0;
2.当x1与x2均大于等于0的时候,要能真正画出这样的情况。观察发现,仅当儿子向上传递的权值分配很畸形的时候才画不出来。设tm为儿子中向上传递权值的最大值,当tm>Ai的时候,就不能画出x1条第一种路径,x2条第二种路径。动手模拟一下就可以看出来。
最后,看一下整棵树的根节点是不是x1等于0,若是的话,证明找到了可行解,因为经过根节点的只能是第二种边。
#include <cstdio>#include <vector>#include <cstdlib>#include <algorithm>using namespace std;typedef long long ll;typedef unsigned int uii;const int maxn=100005;int n,a,b;ll A[maxn];vector<int> tr[maxn];ll dfs(int u,int fa) { if (tr[u].size()==1) return A[u]; ll tot=0,x2=0,x1=0,mm,tm=0; for (uii i=0;i<tr[u].size();++i) { if (tr[u][i]==fa) continue; mm=dfs(tr[u][i],u); tm=max(tm,mm); tot+=mm; } x2=tot-A[u]; x1=A[u]-x2; if (x1<0||x2<0||A[u]<tm||(x1>0&&fa==-1)) { puts("NO"); exit(0); } return x1;}int main(){ scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%lld",&A[i]); if (n==1) { puts(A[1]?"NO":"YES"); return 0; } for (int i=0;i<n-1;++i) { scanf("%d%d",&a,&b); tr[a].push_back(b); tr[b].push_back(a); } if (n==2) puts(A[1]==A[2]?"YES":"NO"); else { for (int i=1;i<=n;++i) if (tr[i].size()>1) { dfs(i,-1); break; } puts("YES"); } return 0;}
1 0
- AtCoder Grant Contest 010 C - Cleaning dfs+逻辑+dp思想
- AtCoder Grant Contest 010 C - Cleaning DP, DFS,思维题 2017/2/6
- AtCoder Grant Contest 10 F - Tree Game 博弈 dfs
- AtCoder Beginner Contest 044 C (dp)
- AtCoder Grand Contest 010
- AtCoder Grand Contest 010
- Atcoder Grand Contest 013C
- AtCoder Beginner Contest 059 C
- AtCoder Regular Contest 077-C
- AtCoder Grand Contest 017 C
- AtCoder Regular Contest 078-C
- AtCoder Beginner Contest 067 C
- AtCoder Beginner Contest 067 C
- 【AtCoder】 Grand Contest 018 C
- AtCoder Regular Contest 079-C
- AtCoder Beginner Contest 069 C
- AtCoder Regular Contest 080-C
- AtCoder Grand Contest 019 C
- 【DP入门】开心的小明(01背包)
- 项目打包上架
- 浅析Spark的RangePartitioner
- Android Sensor感应器介绍(三)获取用户移动方向,指南针原理
- 存储过程返回参数的方法(也是执行动态sql 实现列名成为变量的功能)
- AtCoder Grant Contest 010 C - Cleaning dfs+逻辑+dp思想
- 关于DOM的初步认识
- 数据结构用递归和非递归方法实现二分查找法
- 计算一个数组中相同元素对的数目
- MQTT初体验mosquitto的安装和使用
- sun.misc.BASE64Encoder找不到jar包的解决方法
- POJ 1837 Balance DP 二维背包
- flume学习(一)——安装和一个简单的netcat程序
- 一次生产事故的优化经历