题面

CJY很喜欢吃奶酪,于是YJC弄到了一些奶酪,现在YJC决定和CJY分享奶酪。

YJC弄到了n-1块奶酪,于是他把奶酪挂在了一棵n个结点的树上,每根树枝上挂一块奶酪,每块奶酪都有重量。

YJC和CJY决定这样分奶酪:首先砍掉一根树枝,把树分成两部分,每人取一部分,然后各自在自己取的那部分树上选择一条路径并取走路径上的奶酪,然后把剩下的奶酪拿去喂老鼠。

两人都想让自己取走总重量尽量大的奶酪,但他们不知道砍掉哪一根树枝最好。所以他们想让你计算,对于每一根树枝,砍掉之后每个人取走的奶酪的总重量的最大值。

对于100%的数据,保证n<=4*106,w<=106

100

可以利用树形dp直接做。

维护:

1.一个点往下的最长链\(f_i\);

2.一个点往下的次长链\(g_i\);

3.一个点往下的次次长链\(h_i\);

4.一个子树内的最长链\(mx_i\);

5.一个点的所有儿子\(mx\)的最大值\(mxx_i\);

6.一个点的所有儿子\(mx\)的次大值\(mxxx_i\);

7.一个点往上走的最长链\(F_i\);

8.不包含一个点及其子树的最长链\(Mx_i\)

最后答案就是\(mx\)和\(Mx\)。

时间复杂度为\(O(n)\)。

为什么可以用树形dp

树静态。

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define ll long long
#define fo(i,x,y) for(ll i=x;i<=y;i++)
#define fd(i,x,y) for(ll i=x;i>=y;i--)
using namespace std;
const char* fin="cheese.in";
const char* fout="cheese.out";
const ll inf=0x7fffffff;
const ll maxn=4000007,maxm=maxn*2;
const ll mo=2333333333333333;
ll n,bz[maxn],id,fi[maxn],la[maxm],ne[maxm],va[maxm],tot=1,tmb,ban;
ll f[maxn],g[maxn],h[maxn],mx[maxn],mxx[maxn],mxxx[maxn],fa[maxn],F[maxn],Mx[maxn];
ll ans,ans1,ans2;
void add_line(ll a,ll b,ll c){
tot++;
ne[tot]=fi[a];
la[tot]=b;
va[tot]=c;
fi[a]=tot;
}
void dfs(ll v,ll from){
for(ll k=fi[v];k;k=ne[k])
if (la[k]!=from){
fa[la[k]]=v;
dfs(la[k],v);
mx[v]=max(mx[la[k]],mx[v]);
ll tmp=f[la[k]]+va[k];
if (tmp>=f[v]){
h[v]=g[v];
g[v]=f[v];
f[v]=tmp;
}else if (tmp>=g[v]){
h[v]=g[v];
g[v]=tmp;
}else if (tmp>=h[v]) h[v]=tmp;
if (mx[la[k]]>=mxx[v]){
mxxx[v]=mxx[v];
mxx[v]=mx[la[k]];
}else if (mx[la[k]]>=mxxx[v]) mxxx[v]=mx[la[k]];
}
mx[v]=max(mx[v],f[v]+g[v]);
}
void Dfs(ll v,ll from){
for(ll k=fi[v];k;k=ne[k])
if (la[k]!=from){
Mx[la[k]]=Mx[v];
if (mx[la[k]]==mxx[v]) Mx[la[k]]=max(Mx[la[k]],mxxx[v]);
else Mx[la[k]]=max(Mx[la[k]],mxx[v]);
if (f[v]==f[la[k]]+va[k]){
F[la[k]]=max(F[v]+va[k],g[v]+va[k]);
Mx[la[k]]=max(Mx[la[k]],g[v]+max(h[v],F[v]));
}else{
F[la[k]]=max(F[v]+va[k],f[v]+va[k]);
if (g[v]==f[la[k]]+va[k]) Mx[la[k]]=max(Mx[la[k]],f[v]+max(h[v],F[v]));
else Mx[la[k]]=max(Mx[la[k]],f[v]+max(g[v],F[v]));
}
Dfs(la[k],v);
}
}
ll read(){
ll x=0;
char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
n=read();
fo(i,1,n-1){
ll j=read();
ll k=read();
ll l=read();
add_line(j,k,l);
add_line(k,j,l);
}
dfs(1,0);
Dfs(1,0);
fo(i,1,n-1){
ll u=la[i*2+1],v=la[i*2];
if (fa[v]==u) swap(u,v);
ans1=mx[u];
ans2=Mx[u];
ans=(ans+max(ans1,ans2)*23333+min(ans2,ans1)*2333+233*i*i+23*i+2)%mo;
//printf("%lld %lld\n",ans1,ans2);
}
cout<<ans<<endl;
return 0;
}

【JZOJ5071】【GDSOI2017第二轮模拟】奶酪 树形dp的更多相关文章

  1. 【JZOJ5068】【GDSOI2017第二轮模拟】树 动态规划+prufer序列

    题面 有n个点,它们从1到n进行标号,第i个点的限制为度数不能超过A[i]. 现在对于每个s (1 <= s <= n),问从这n个点中选出一些点组成大小为s的有标号无根树的方案数. 10 ...

  2. bzoj 2159 Crash 的文明世界 && hdu 4625 JZPTREE ——第二类斯特林数+树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2159 学习材料:https://blog.csdn.net/litble/article/d ...

  3. P4827 [国家集训队] Crash 的文明世界(第二类斯特林数+树形dp)

    传送门 对于点\(u\),所求为\[\sum_{i=1}^ndis(i,u)^k\] 把后面那堆东西化成第二类斯特林数,有\[\sum_{i=1}^n\sum_{j=0}^kS(k,j)\times ...

  4. bzoj 2159 Crash 的文明世界 & hdu 4625 JZPTREE —— 第二类斯特林数+树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2159 使用公式:\( n^{k} = \sum\limits_{i=0}^{k} S(k,i ...

  5. 美团2017年CodeM大赛-初赛B轮 黑白树 (树形dp)

    大意: 给定树, 初始每个点全为白色, 点$i$有权值$k_i$, 表示选择$i$后, 所有距离$i$小于$k_i$的祖先(包括i)会变为黑色, 求最少选多少个点能使所有点变为黑色. 链上情况的话, ...

  6. BZOJ 2159: Crash 的文明世界(组合数学+第二类斯特林数+树形dp)

    传送门 解题思路 比较有意思的一道数学题.首先\(n*k^2\)的做法比较好想,就是维护一个\(x^i\)这种东西,然后转移的时候用二项式定理拆开转移.然后有一个比较有意思的结论就是把求\(x^i\) ...

  7. GDOI2017第二轮模拟day1 总结

    平民比赛 这场比赛的暴力分非常友好. 但是我并没有拿到全部的暴力分. 1(暴力分\(60/100\)) 暂时我可以拿的暴力分为\(30/100\),直接mst模拟即可. 然而当时打了个辣鸡莫队,结果爆 ...

  8. BZOJ2159 Crash 的文明世界 【第二类斯特林数 + 树形dp】

    题目链接 BZOJ2159 题解 显然不能直接做点分之类的,观察式子中存在式子\(n^k\) 可以考虑到 \[n^k = \sum\limits_{i = 0} \begin{Bmatrix} k \ ...

  9. [jzoj5073 GDOI2017第二轮模拟] 影魔

    Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵 ...

随机推荐

  1. MathType插件安装

    1 安装包下载 版本号:7.4 下载 提取码:fxma 2 安装方法 用安装包内的Key激活即可.软件激活后不能升级. 注意:必须断网或者加入防火墙阻止联网使用! 3 可能遇到的问题 当安装完Math ...

  2. Ubuntu 卸载nvidia驱动

    1.切换为集成显卡 如果没有,那么先切换到字符界面 2.卸载驱动 sudo apt-get --purge remove nvidia* sudo apt autoremove To remove C ...

  3. Redis高级命令的使用学习

  4. [Swoole系列入门教程 3] 心跳检测

    一.Swoole 的4大知识点: 1.TCP/UDP服务器 2.微服务 3.协程 二.同步与异步: 同步买奶茶:小明点单交钱,然后等着拿奶茶: 异步买奶茶:小明点单交钱,店员给小明一个小票,等小明奶茶 ...

  5. 廖雪峰Java10加密与安全-2加密算法-1URL编码

    1.URL编码 URL编码是浏览器发送数据给服务器时使用的编码. 如通过百度搜索美女: 编码前:https://www.baidu.com/s?wd=美女 编码后:https://www.baidu. ...

  6. RuntimeError: You called this URL via POST, but the URL doesn’t end in a slash and you have APPEND_SLASH set.

    做公众号测试的时候,发现了个问题: 提交表单报错:RuntimeError: You called this URL via POST, but the URL doesn’t end in a sl ...

  7. 深入浅出 Java Concurrency (23): 并发容器 part 8 可阻塞的BlockingQueue (3)[转]

    在Set中有一个排序的集合SortedSet,用来保存按照自然顺序排列的对象.Queue中同样引入了一个支持排序的FIFO模型. 并发队列与Queue简介 中介绍了,PriorityQueue和Pri ...

  8. Python学习之循环--绕圈圈(蛇形盘)

    效果图: 注意哦,右边多出来的一点不是程序有问题,是打印的时候我用的\t,但100,三个字符顶格的时候给顶出去的,我太懒了,不想再调输出格式了,就这么凑合看吧 实现代码: sum = int(inpu ...

  9. Nginx与PHP工作原理

    Nginx的工作原理 1.Nginx的模块与工作原理 Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端请求映射到一个location bl ...

  10. python-web-下载所有xkcd漫画

    下载所有xkcd漫画 # downloads every single xkcd comic import requests,os,bs4 url='http://xkcd.com' # start ...