设f[i][j]为由根进入遍历完i子树,最后一个到达的点是j时的最小代价,g[i][j]为由子树内任意一点开始遍历完i子树,最后一个到达的点是j时的最小代价,因为是一棵完全二叉树,状态数量是nlogn的。转移考虑四种走法:根→左子树→右子树;根→右子树→左子树;左子树→根→右子树;右子树→根→左子树 即可。好像和大多数题解不一样,明明感觉这种做法比较显然。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 200010
#define inf 100000000000000000ll
int n,a[N],p[N],deep[N],t;
vector<int> son[N];
vector<long long> f[N],g[N];
struct data{int to,nxt,len;
}edge[N];
void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
void dfs(int k)
{
int cnt=;
for (int i=p[k];i;i=edge[i].nxt)
{
cnt++;
deep[edge[i].to]=deep[k]+edge[i].len;
dfs(edge[i].to);
for (int j=;j<son[edge[i].to].size();j++)
son[k].push_back(son[edge[i].to][j]);
}
son[k].push_back(k);
if (cnt==) {f[k].push_back();g[k].push_back();return;}
if (cnt==)
{
long long v=inf;
for (int i=;i<son[k].size()-;i++)
f[k].push_back(f[edge[p[k]].to][i]+1ll*edge[p[k]].len*a[edge[p[k]].to]),
g[k].push_back(f[k][i]),v=min(v,f[edge[p[k]].to][i]+1ll*(deep[son[edge[p[k]].to][i]]-deep[k])*a[k]);
f[k].push_back(inf),g[k].push_back(v);
}
else
{
long long P=inf,Q=inf,X=inf,Y=inf;
int x=edge[p[k]].to,y=edge[edge[p[k]].nxt].to,w=edge[p[k]].len,v=edge[edge[p[k]].nxt].len;
for (int i=;i<son[x].size();i++)
P=min(P,f[x][i]+1ll*w*a[x]+1ll*(deep[son[x][i]]-deep[k])*a[y]),
X=min(X,g[x][i]+1ll*(deep[son[x][i]]-deep[k])*a[k]);
for (int i=;i<son[y].size();i++)
Q=min(Q,f[y][i]+1ll*v*a[y]+1ll*(deep[son[y][i]]-deep[k])*a[x]),
Y=min(Y,g[y][i]+1ll*(deep[son[y][i]]-deep[k])*a[k]);
X=min(X,P),Y=min(Y,Q);
for (int i=;i<son[x].size();i++)
f[k].push_back(Q+1ll*w*a[x]+f[x][i]),g[k].push_back(Y+1ll*w*a[x]+f[x][i]);
for (int i=;i<son[y].size();i++)
f[k].push_back(P+1ll*v*a[y]+f[y][i]),g[k].push_back(X+1ll*v*a[y]+f[y][i]);
f[k].push_back(inf),g[k].push_back(inf);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4446.in","r",stdin);
freopen("bzoj4446.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
for (int i=;i<=n;i++) a[i]=read();
for (int i=;i<n;i++) addedge(i+>>,i+,read());
dfs();
long long ans=inf;
for (int i=;i<son[].size();i++) ans=min(ans,g[][i]);
cout<<ans;
return ;
}

BZOJ4446 SCOI2015小凸玩密室(树形dp)的更多相关文章

  1. [BZOJ4446]SCoi2015 小凸玩密室 树形DP(烧脑高能预警)

    4446: [Scoi2015]小凸玩密室 Time Limit: 10 Sec  Memory Limit: 128 MB Description 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点 ...

  2. BZOJ4446:[SCOI2015]小凸玩密室(树形DP)

    Description 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室. 每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要 ...

  3. LUOGU P4253 [SCOI2015]小凸玩密室(树形dp)

    传送门 解题思路 玄学树形\(dp\),题目描述极其混乱...看错了两次题,设首先根据每次必须点完子树里的灯才能点别的,那么点灯情况只有两种,第一种是点到某一个祖先,第二种是点到某一个祖先的兄弟.所以 ...

  4. BZOJ.4446.[SCOI2015]小凸玩密室(树形DP)

    BZOJ LOJ 洛谷 (下面点亮一个灯泡就说成染色了,感觉染色比较顺口... 注意完全二叉树\(\neq\)满二叉树,点亮第一个灯泡\(\neq\)第一次点亮一号灯泡,根节点应该就是\(1\)... ...

  5. BZOJ4446 [Scoi2015]小凸玩密室 【树形Dp】

    题目 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯 泡即可逃出密室.每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要花费,之后每点亮4 ...

  6. 2019.03.26 bzoj4446: [Scoi2015]小凸玩密室(树形dp)

    传送门 题意简述: 给一棵完全二叉树,有点权aia_iai​和边权,每个点有一盏灯,现在要按一定要求点亮: 任意时刻点亮的灯泡必须连通 点亮一个灯泡后必须先点亮其子树 费用计算如下:点第一盏灯不要花费 ...

  7. BZOJ4446: [Scoi2015]小凸玩密室

    用ui,j表示走完i的子树后走到i的深度为j的祖先的兄弟的最小代价: 用vi,j表示走完i的子树后走到i的深度为j的祖先的最小代价,用u算出v. 枚举起点,计算答案. #include<bits ...

  8. [bzoj4446] [loj#2009] [Scoi2015] 小凸玩密室

    Description 小凸和小方相约玩密室逃脱,这个密室是一棵有 \(n\) 个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室.每个灯泡有个权值 \(Ai\) ,每条边也有个权值 \ ...

  9. bzoj 4446: [Scoi2015]小凸玩密室

    Description 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯 泡即可逃出密室.每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要 ...

随机推荐

  1. Yaf学习(一)----Linux安装Yaf

    1.简介 Yaf,全称 Yet Another Framework,是一个高性能的PHP开发框架,采用PHP扩展实现(c语言).Blablablabla....... 2.环境 2.1 虚拟机 虚拟机 ...

  2. Jackson 触发的String.intern() bug, 导致内存持续增加,JVM-Java内存泄漏

    我在本地用Jackson可以复现这个问题了. import java.io.IOException; import java.util.Map; import java.util.Random; im ...

  3. 5.Python的语言特点

    前言   Python有哪些语言特点?可以列出的特点很多,例如,<Python核心编程>第二版列出了十多条特点.本文的三个特点是笔者学习Python的体会,其他特点有体会之后再写,笔者是这 ...

  4. struts2架构网站漏洞修复详情与利用漏洞修复方案

    struts2从开发出来到现在,很多互联网企业,公司,平台都在使用apache struts2系统来开发网站,以及应用系统,这几年来因为使用较多,被攻击者挖掘出来的struts2漏洞也越来越,从最一开 ...

  5. linux-课题练习1

    1.创建组testgroup: 2.创建用户a2012,先采用默认设置创建,然后使该用户加入testgroup组. 3.创建用户a2013,其用户主目录为/tmp/a2013,其主组为testgrou ...

  6. C++11中rvalue references的使用

    Rvalue references are a feature of C++ that was added with the C++11 standard. The syntax of an rval ...

  7. itop-4412开发板学习-内核信号量

    1. 翻翻书看下,linux提供两种信号量,内核信号量,由内核控制路径使用,System V IPC信号量,由用户态进程使用.下面的就是内核部分的信号量.内核信号量类似于自旋锁,当锁关闭着时,不允许内 ...

  8. vs2015-Cordova开发安卓应用环境搭建

    之前看到过用html5+css+js就可以开发跨平台的应用,然后发现vs2015里就有个Cordova项目所以就想试试,但并不是这么顺利.刚开始对安卓环境一点也不了解,就到处百度搜索.终于成功了. 首 ...

  9. 问题:docker pull 用户登陆tricky,Error response from daemon: unauthorized: incorrect username or password

    问题描述: PS C:\WINDOWS\system32> docker pull rabbitmqUsing default tag: latest Please login prior to ...

  10. 我所认识的XPath

    实例demo 测试demo所需要xml测试数据 <?xml version="1.0" encoding="iso-8859-1"?> <bo ...