JZOJ 4923. 巧克力狂欢
来源:互联网 发布:java如何编译 编辑:程序博客网 时间:2024/06/10 00:43
题目
Alice和Bob有一棵树(无根、无向),在第i个点上有ai个巧克力。首先,两人个选择一个起点(不同的),获得点上的巧克力;接着两人轮流操作(Alice先),操作的定义是:在树上找一个两人都没选过的点并获得点上的巧克力,并且这个点要与自己上一次选的点相邻。当有一人无法操作 时,另一个人可以继续操作,直到不能操作为止。因为Alice和Bob是好朋友,所以他们希望两人得到的巧克力总和尽量大,请输出最大总和。
题解
(这种方法的题解很难写啊)
果断树形DP。设F[x]表示一定不能再往上继续扩展(由于这是树形DP,先DP儿子的值,然后再将儿子的DP值返回给父亲,所以父亲加上儿子的DP值就叫向上扩展)的最大权值,ans[x]表示最大的权值(显然ans[x]包括f[x]),那么f[x]有几种转移:1、f[x]=max(f[son x],ans[x])。//f[son x]表示不选择x这个点。2、f[x]=max(f[x],最长链+次长链+当前子树中的最长"^"形链)。3、f[x]=max(f[x],当前子树中的最长"^"形链+当前子树中的次长"^"形链)//这种情况显然。4、f[x]=max(f[x],当前子树中最大的ans值+最长链)ans[x]的转移如下:ans[x]=max(ans[x],最长链+当前子树中的最长"^"形链)。//这种情况显然。另外,如果这些值在同一个子树中,那么就换次大的值,如果还不行,就换第3大的值。比如说,对于方程式2,如果当前子树中的最长"^"形链在最长链或次长链的子树中,就选当前子树 中的次长"^"形链,如果还是在,就选当前子树中的第3长"^"形链。
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#define N 200010#define LL long long#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;LL x,y,i,j,n,tot,ANS;LL a[N],ls[N],g[N],f[N],ans[N];LL head[N],go[N*2],next[N*2];void lb(LL x,LL y){ go[++tot]=y; next[tot]=head[x]; head[x]=tot;}void dg(LL x,LL fa){ LL i,c1,c2,c3,g1,g2,g3,p1,p2; c1=c2=c3=g1=g2=g3=p1=p2=0; for(i=head[x];i;i=next[i]) { LL now=go[i]; if (now==fa) continue; dg(now,x); if (ls[now]>ls[c1]) c3=c2,c2=c1,c1=now;else if (ls[now]>ls[c2]) c3=c2,c2=now;else if (ls[now]>ls[c3]) c3=now; if (g[now]>g[g1]) g3=g2,g2=g1,g1=now;else if (g[now]>g[g2]) g3=g2,g2=now;else if (g[now]>g[g3]) g3=now; if (f[now]>ans[p1]) p2=p1,p1=now;else if (f[now]>ans[p2]) p2=now; f[x]=max(f[now],ans[x]); } g[x]=max(g[g1],a[x]+ls[c1]+ls[c2]); ls[x]=ls[c1]+a[x]; f[x]=max(f[x],g[g1]+g[g2]); ans[x]=ans[p1]+a[x]; { if (c1!=g1 && c2!=g1) f[x]=max(f[x],a[x]+ls[c1]+ls[c2]+g[g1]); if (c1!=g1 && c3!=g1) f[x]=max(f[x],a[x]+ls[c1]+ls[c3]+g[g1]); if (c2!=g1 && c3!=g1) f[x]=max(f[x],a[x]+ls[c2]+ls[c3]+g[g1]); if (c1!=g2 && c2!=g2) f[x]=max(f[x],a[x]+ls[c1]+ls[c2]+g[g2]); if (c1!=g2 && c3!=g2) f[x]=max(f[x],a[x]+ls[c1]+ls[c3]+g[g2]); if (c2!=g2 && c3!=g2) f[x]=max(f[x],a[x]+ls[c2]+ls[c3]+g[g2]); if (c1!=g3 && c2!=g3) f[x]=max(f[x],a[x]+ls[c1]+ls[c2]+g[g3]); if (c1!=g3 && c3!=g3) f[x]=max(f[x],a[x]+ls[c1]+ls[c3]+g[g3]); if (c2!=g3 && c3!=g3) f[x]=max(f[x],a[x]+ls[c2]+ls[c3]+g[g3]); } { if (c1!=p1) f[x]=max(f[x],a[x]+ls[c1]+ans[p1]); if (c1!=p2) f[x]=max(f[x],a[x]+ls[c1]+ans[p2]); if (c2!=p1) f[x]=max(f[x],a[x]+ls[c2]+ans[p1]); if (c2!=p2) f[x]=max(f[x],a[x]+ls[c2]+ans[p2]); if (c3!=p1) f[x]=max(f[x],a[x]+ls[c3]+ans[p1]); if (c3!=p2) f[x]=max(f[x],a[x]+ls[c3]+ans[p2]); } { if (c1!=g1) ans[x]=max(ans[x],a[x]+ls[c1]+g[g1]); if (c2!=g1) ans[x]=max(ans[x],a[x]+ls[c2]+g[g1]); if (c3!=g1) ans[x]=max(ans[x],a[x]+ls[c3]+g[g1]); if (c1!=g2) ans[x]=max(ans[x],a[x]+ls[c1]+g[g2]); if (c2!=g2) ans[x]=max(ans[x],a[x]+ls[c2]+g[g2]); if (c3!=g2) ans[x]=max(ans[x],a[x]+ls[c3]+g[g2]); if (c1!=g3) ans[x]=max(ans[x],a[x]+ls[c1]+g[g3]); if (c2!=g3) ans[x]=max(ans[x],a[x]+ls[c2]+g[g3]); if (c3!=g3) ans[x]=max(ans[x],a[x]+ls[c3]+g[g3]); }}int main(){ scanf("%lld",&n); fo(i,1,n) scanf("%lld",&a[i]); fo(i,1,n-1) { scanf("%lld %lld",&x,&y); lb(x,y);lb(y,x); } dg(1,-1); ANS=max(f[1],ans[1]); printf("%lld",ANS);}
2 0
- JZOJ 4923. 巧克力狂欢
- 【JZOJ 4923】【NOIP2017提高组模拟12.17】巧克力狂欢
- 【JZOJ 4923】 巧克力狂欢 树的直径经典问题
- 求hack or 证明(【JZOJ 4923】 【NOIP2017提高组模拟12.17】巧克力狂欢)
- 【JZOJ4923】巧克力狂欢
- [JZOJ4923] 巧克力狂欢
- 【NOIP2017提高组模拟12.17】巧克力狂欢
- JZOJ4923. 【NOIP2017提高组模拟12.17】巧克力狂欢
- 【JZOJ4923】【NOIP2017提高组模拟12.17】巧克力狂欢
- 巧克力
- 巧克力
- 巧克力
- 巧克力
- 巧克力
- 巧克力
- 集体狂欢
- 巧克力2
- 巧克力3
- C语言实现通讯录系统——容量自增,文件版本
- kafka.storage为kafka时如修改设置用户组的offset
- 8.12 k-生成树(k-SPANNING TREE)证明 等题
- 开发工具-Github学习笔记
- RHEL6.1使用rpmbuild方式升级内核
- JZOJ 4923. 巧克力狂欢
- 数据库中的索引
- vim简化ctags+taglist安装
- 主从复制配置
- 微信播放视频花屏解决办法
- storm的单节点安装以及简单操作
- Mybatisd的逆向工程
- 4602: [Sdoi2016]齿轮
- IE不兼容placeholder的解决方案