P3354 题解

题目传送门

一道很恶心的树形dp 但是我喜欢

题目大意:

一片海旁边有一条树状的河,入海口有一个大伐木场,每条河的分叉处都有村庄。建了伐木场的村庄可以直接处理木料,否则要往下游的伐木场运,运费为每吨每千米 \(1\) 分钱。现在要在一些村庄建 \(k\) 个伐木场,求建完之后最小的运输费用。

设计状态:

\[f(u,z,k,l):
\begin{cases}
u:以第i个点为根的子树 \\
z:离点i最近的伐木场的位置(祖先) \\
k:该子树被分配了k个伐木场 \\
l:0或1,表示是否在此节点建伐木场
\end{cases}
\]

转移

\[f_{u,z,k}=
\begin{cases}
f_{u,z,k,0}=\min\limits_{v\in son}f_{u,z,k-l,0}+f_{v,z,l,0}\\
f_{u,z,k,1}=\min\limits_{v\in son}f_{u,z,k-l,1}+f_{v,u,l,0}\ \ (此时u有伐木场,它的儿子们可以直接运往它)
\end{cases}
\]

\(l\) 为给一个儿子分配的 \(k\) 个伐木场

然后对是否建伐木场进行合并,即:

\[f_{u,z,k}=\min(f_{u,z,k,0}+w_u*(d_u-d_z)\ ,\ f_{u,z,k-1,1})
\]

初始状态

\[f_{u,z,j,0}=f_{u,z,j,0}+f_{v,z,0,0}\\
f_{u,z,j,1}=f_{u,z,j,1}+f_{v,u,0,0}
\]

代码:

#include <bits/stdc++.h>
#define _for(i,a,b) for(int i=a;i<=b;++i)
#define for_(i,a,b) for(int i=a;i>=b;--i)
#define ll long long
using namespace std;
const int N=110,inf=0x3f3f3f3f;
ll n,k,a,fm[N],c,w[N],d[N],v;
ll f[N][N][N][2];
vector<ll>s[N];
//fm:祖先,d:深度,s:儿子们
void dp(ll u){
fm[++c]=u;//把该点压入祖先们
int sz=s[u].size();
_for(i,0,sz-1){
int v=s[u][i];
d[v]+=d[u];
dp(v);
_for(i,1,c){//重点部分!!
for_(j,k,0){
//初始化
f[u][fm[i]][j][0]+=f[v][fm[i]][0][0];
f[u][fm[i]][j][1]+=f[v][u][0][0];
_for(l,0,j){
//转移
f[u][fm[i]][j][0]=min(f[u][fm[i]][j][0],f[u][fm[i]][j-l][0]+f[v][fm[i]][l][0]);
f[u][fm[i]][j][1]=min(f[u][fm[i]][j][1],f[u][fm[i]][j-l][1]+f[v][u][l][0]);
}
}
}
}_for(i,1,c){//合并
f[u][fm[i]][0][0]+=w[u]*(d[u]-d[fm[i]]);
_for(j,1,k)f[u][fm[i]][j][0]=min(f[u][fm[i]][j][0]+w[u]*(d[u]-d[fm[i]]),f[u][fm[i]][j-1][1]);
}
--c;//把该点弹出去
}
int main(){
scanf("%lld%lld",&n,&k);
_for(i,1,n){
scanf("%lld%lld%lld",&w[i],&a,&d[i]);
s[a].push_back(i);
}
dp(0);
printf("%lld\n",f[0][0][k][0]);
return 0;
}

「题解报告」P3354的更多相关文章

  1. 「题解报告」 P3167 [CQOI2014]通配符匹配

    「题解报告」 P3167 [CQOI2014]通配符匹配 思路 *和?显然无法直接匹配,但是可以发现「通配符个数不超过 \(10\) 」,那么我们可以考虑分段匹配. 我们首先把原字符串分成多个以一个通 ...

  2. 「题解报告」P4577 [FJOI2018]领导集团问题

    题解 P4577 [FJOI2018]领导集团问题 题解区好像没有线段树上又套了二分的做法,于是就有了这片题解. 题目传送门 怀着必 WA 的决心交了两发,一不小心就过了. 题意 求一个树上最长不下降 ...

  3. 「题解报告」P2154 虔诚的墓主人

    P2154 虔诚的墓主人 题解 原题传送门 题意 在 \(n\times m\) 一个方格上给你 \(w\) 个点,求方格里每个点正上下左右各选 \(k\) 个点的方案数. \(1 \le N, M ...

  4. 「题解报告」SP16185 Mining your own business

    题解 SP16185 Mining your own business 原题传送门 题意 给你一个无向图,求至少安装多少个太平井,才能使不管那个点封闭,其他点都可以与有太平井的点联通. 题解 其他题解 ...

  5. 「题解报告」Blocks

    P3503 Blocks 题解 原题传送门 思路 首先我们可以发现,若 \(a_l\) ~ \(a_r\) 的平均值大于等于 \(k\) ,则这个区间一定可以转化为都大于等于 \(k\) 的.我们就把 ...

  6. 「题解报告」CF1067A Array Without Local Maximums

    大佬们的题解都太深奥了,直接把转移方程放出来让其他大佬们感性理解,蒟蒻们很难理解,所以我就写了一篇让像我一样的蒟蒻能看懂的题解 原题传送门 动态规划三部曲:确定状态,转移方程,初始状态和答案. --神 ...

  7. 「题解报告」P7301 【[USACO21JAN] Spaced Out S】

    原题传送门 神奇的5分算法:直接输出样例. 20分算法 直接把每个点是否有牛的状态DFS一遍同时判断是否合法,时间复杂度约为\(O(2^{n^2})\)(因为有判断合法的剪枝所以会比这个低).而在前四 ...

  8. 「GXOI / GZOI2019」简要题解

    「GXOI / GZOI2019」简要题解 LOJ#3083. 「GXOI / GZOI2019」与或和 https://loj.ac/problem/3083 题意:求一个矩阵的所有子矩阵的与和 和 ...

  9. 【题解】#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT)

    [题解]#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT) 之前做这道题不理解,有一点走火入魔了,甚至想要一本近世代数来看,然后通过人类智慧思考后发现, ...

随机推荐

  1. XDEBUG 选项

    到官网 http://www.xdebug.com/download.php 下载 找到对应PHP版本的 Xdebug ,后面带 TS 的为线程安全,本机环境为 win7 64 + php-5.5.1 ...

  2. Bika LIMS 开源LIMS集——ERD实体关系定义(数据库设计)

    系统数据分类 数据分为四类: template 模板,基础静态数据 static 静态数据,核心静态数据,检测方法等 dynamic 动态数据,样品检测流程数据 organisation 组织机构数据 ...

  3. 29.MySQL高级SQL语句

    MySQL高级SQL语句 目录 MySQL高级SQL语句 创建两个表 SELECT DISTINCT WHERE AND OR IN BETWEEN 通配符 LIKE ORDER BY 函数 数学函数 ...

  4. 《Java笔记——基础语法》

    Java笔记--基础语法       一.字符串的拼接: 例如: System.out.println(""+"");     二.换行语句: 例如: Syst ...

  5. javascript写无缝平移的轮播图

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. python小题目练习(九)

    题目:将美元转化为人民币 需求:实现如图所示需求  代码展示: """Author:mllContent:将美元转化为人民币Date:2020-11-23"&q ...

  7. CompletableFuture的入门

    runAsync 和 supplyAsync runAsync接受一个Runable的实现,无返回值 CompletableFuture.runAsync(()->System.out.prin ...

  8. Day05 表格

    表格 <table width="300" border="1" cellspacing="0"> <caption> ...

  9. 字符输入流_Reader类&FileReader类介绍和字符输入读取字符数据

    java.io.Reader:字符输入流的最顶层父类,其中定义了一些共性的成员方法,是一个抽象类共性的成员方法 int read() 读取单个字符并返回 int read(char[] cbuf) 将 ...

  10. 攻防世界MISC—进阶区11-20

    11.János-the-Ripper 得到未知类型的文件,010 Editor打开后看到pk,得知是真加密的zip文件. 密码在文件中没有提示,根据题目名字,János-the-Ripper Ján ...