【JZOJ 4923】 巧克力狂欢 树的直径经典问题
来源:互联网 发布:软件开发招标文件 编辑:程序博客网 时间:2024/04/30 12:38
Description
给你一棵树,每个点有权,求出树中两条不相交的路径,使得两个路径上的点权总和最大
输出这个最大值
对于100%的数据,n<=200000,0<=ai<=1000000000(1e9)
Analysis
这道题有多种方法,可以DP,用f[i][0/1]来乱搞
这是一个神奇的根据直径性质的方法
默认直径是横着放的
首先求出直径,再求出不与直径相交的最长路径,求和作为答案
求出直径上每个点左右两侧的最长路径(设为l[v],r[v]):注意这个最长路径可能是延伸到直径该侧端点,也可能延伸到这个点某个子树下面
这是可以O(n)求的
然后在直径上随机选u,v(u在v左边),用l[u]+r[v]更新答案
求前后缀最大值就能做到O(n)了
Code
#include<cstdio>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,b,a) for(int i=b;i>=a;i--)#define efo(i,v) for(int i=last[v];i;i=next[i])using namespace std;typedef long long ll;const int N=200010,M=N*2;int n,m,tot,u1,u2,v1,v2,d[N];ll mx,ans,a[N],b[N],c[N],sl[N],sr[N],l[N],r[N],ml[N],mr[N];int fa[N],f[N],g[N],to[M],next[M],last[N];bool tag,bz[N];void link(int u,int v){ to[++tot]=v,next[tot]=last[u],last[u]=tot;}void dfs1(int v,int fr,ll k){ if(k>mx) mx=k,v1=v; efo(i,v) { int u=to[i]; if(u==fr || bz[u]) continue; dfs1(u,v,k+a[u]); }}void dfs2(int v,int fr,ll k){ if(k>mx) mx=k,v2=v; if(!tag) fa[v]=fr; efo(i,v) { int u=to[i]; if(u==fr || bz[u]) continue; dfs2(u,v,k+a[u]); }}void get(int i){ mx=0;dfs1(i,i,a[i]); mx=0;dfs2(v1,v1,a[v1]); ll t1=0,t2=0; for(int v=v1;;) { t1+=a[v]; if(v==i) break; v=fa[v]; } for(int v=v2;;) { t2+=a[v]; if(v==i) break; v=fa[v]; } b[i]=max(t1,t2); if(v1==v2) c[i]=t1; else c[i]=t1+t2-a[i];}int main(){ int u,v; scanf("%d",&n); fo(i,1,n) scanf("%d",&a[i]); fo(i,1,n-1) { scanf("%d %d",&u,&v); link(u,v),link(v,u); } dfs1(1,1,a[1]);mx=0; dfs2(v1,v1,a[v1]); u1=v1,u2=v2; ll disu=0,disv=0; for(int u=u2;;) { bz[u]=1,disu+=a[u]; d[++m]=u; if(u==u1) break; u=fa[u]; } tag=1; fo(k,1,m) { int u=d[k]; efo(j,u) { int i=to[j]; if(bz[i]) continue; get(i); disv=max(disv,c[i]); } get(u); } ans=disv+disu; fo(k,1,m) { int u=d[k]; sl[k]=sl[k-1]+a[d[k]]; l[k]=max(c[u],b[u]+sl[k-1]); ml[k]=max(ml[k-1],l[k]); } fd(k,m,1) { int u=d[k]; sr[k]=sr[k+1]+a[d[k]]; r[k]=max(c[u],b[u]+sr[k+1]); mr[k]=max(mr[k+1],r[k]); ans=max(ans,mr[k]+ml[k-1]); } printf("%lld",ans); return 0;}
0 0
- 【JZOJ 4923】 巧克力狂欢 树的直径经典问题
- JZOJ 4923. 巧克力狂欢
- 【JZOJ 4923】【NOIP2017提高组模拟12.17】巧克力狂欢
- 求hack or 证明(【JZOJ 4923】 【NOIP2017提高组模拟12.17】巧克力狂欢)
- 【JZOJ4923】巧克力狂欢
- [JZOJ4923] 巧克力狂欢
- 树的直径问题
- poj-1383-Labyrinth【树的直径】【经典】
- 树的直径问题poj2631
- 求树的直径问题
- POJ 1383 Labyrinth(迷宫问题,树的最大直径,经典问题)
- [jzoj]3555. 【GDKOI2014模拟】树的直径(结论题-树的性质)
- (jzoj snow的追寻)线段树维护树的直径
- 【NOIP2017提高组模拟12.17】巧克力狂欢
- 数据结构中树的直径问题
- 树的直径(最长路)问题
- 洛谷月赛最后的狂欢 2038年问题
- bzoj3124 [Sdoi2013]直径 树的直径
- 如何解决“用apt-get 安装 make提示“无法打开锁文件 /var/lib/dpkg/lock ”
- 【SDOI2009】Super Gcd (高精度gcd)
- Java Vector 类
- LNMP环境+Laravel快速搭建
- 道阻且长 行则将至——android学习总结
- 【JZOJ 4923】 巧克力狂欢 树的直径经典问题
- 《Effective Objective-C 2.0》读书笔记---第四章
- MongoDB的应用场景
- JavaScript中的new的作用
- Android Studio Project debug library show source code does not match the bytecode
- 基于Zedboard的视频处理系统(可缩放显示)
- MyBatis别名的两种实现方式
- iOS启动页广告swift3.0
- XMPP学习2-XMPP通讯原语