JZOJ 4923. 巧克力狂欢
2016-12-19 20:13
211 查看
题目
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 ,ls ,g ,f ,ans ; LL head ,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); }
相关文章推荐
- 【JZOJ 4923】【NOIP2017提高组模拟12.17】巧克力狂欢
- 求hack or 证明(【JZOJ 4923】 【NOIP2017提高组模拟12.17】巧克力狂欢)
- 【JZOJ4923】巧克力狂欢
- 【JZOJ 4923】 巧克力狂欢 树的直径经典问题
- [JZOJ4923] 巧克力狂欢
- 【JZOJ4923】【NOIP2017提高组模拟12.17】巧克力狂欢
- JZOJ4923. 【NOIP2017提高组模拟12.17】巧克力狂欢
- 【NOIP2017提高组模拟12.17】巧克力狂欢
- 【JZOJ5482】第三题
- Jzoj3486 道路改建
- 【JZOJ 5490】 图染色
- JZOJ 2017.12.09【NOIP提高组】模拟赛C组
- [jzoj4598]【NOIP2016模拟7.9】准备食物
- 【JZOJ 3492】【NOIP2013模拟联考12】数数(count)
- 双旦技术盛典,跨年立减狂欢惠
- JZOJ4899. 【NOIP2016提高A组集训第17场11.16】雪之国度
- Jzoj3155 最短路
- [JZOJ5509] 兔子
- Jzoj3169 生产汽车
- bzoj2850 巧克力王国(K-D tree)