什么鬼noip互测题...

这题很显然是树形dp,但设计状态以及转移是个难点

记状态f[i][j][k]表示以i为根节点的子树,离i最近的祖宗节点编号为j放了虫洞(伐木场?),i的子树内放了k个伐木场的方案数

设to为i的某个子节点,当i不放伐木场时,有:

dp[i][j][k]=min(dp[to][j][k-c]+dp[i][j][c])

当i放伐木场时,有:

dp[i][i][k]=min(dp[to][i][k-c]+dp[i][i]c])

最后合并:

dp[i][j][k]+=num[i]*dis[i][j]

dp[i][j][k]=min(dp[i][j][k],dp[i][i][k])

其中dis[i][j]表示从i到j(j为i的某个祖先节点)的距离,可以预处理出来

特别的,当i为叶节点(即i没有子节点)时,dp[i][j][0]=dis[i][j]*num[i]直接赋值

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define ll long long
using namespace std;
int dp[][][];
struct Edge
{
int next;
int to;
}edge[];
int head[];
int dis[][];
int num[];
int f[];
int n,k;
int cnt=;
void init()
{
memset(head,-,sizeof(head));
memset(f,-,sizeof(f));
cnt=;
}
void add(int l,int r)
{
edge[cnt].next=head[l];
edge[cnt].to=r;
head[l]=cnt++;
}
void initdfs(int x)
{
if(x)
{
for(int i=f[x];i!=-;i=f[i])
{
dis[x][i]=dis[x][f[x]]+dis[f[x]][i];
}
dis[x][]=dis[x][f[x]]+dis[f[x]][];
}
for(int i=head[x];i!=-;i=edge[i].next)
{
int to=edge[i].to;
initdfs(to);
}
}
void dfs(int x)
{
if(head[x]==-)
{
for(int i=f[x];i!=-;i=f[i])
{
dp[x][i][]=dis[x][i]*num[x];
}
return;
}
if(x)
{
dp[x][x][]=0x3f3f3f3f;
}
for(int i=head[x];i!=-;i=edge[i].next)
{
int to=edge[i].to;
dfs(to);
for(int j=f[x];j!=-;j=f[j])
{
for(int t=k;t>=;t--)
{
int temp=0x3f3f3f3f;
for(int c=;c<=t;c++)
{
temp=min(temp,dp[x][j][c]+dp[to][j][t-c]);
}
dp[x][j][t]=temp;
}
}
for(int j=k;j>=;j--)
{
int temp=0x3f3f3f3f;
for(int c=(x!=);c<=j;c++)
{
temp=min(temp,dp[x][x][c]+dp[to][x][j-c]);
}
dp[x][x][j]=temp;
}
}
for(int i=f[x];i!=-;i=f[i])
{
for(int j=;j<=k;j++)
{
dp[x][i][j]+=dis[x][i]*num[x];
dp[x][i][j]=min(dp[x][i][j],dp[x][x][j]);
}
}
}
inline int read()
{
int f=,x=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int main()
{
// freopen("girls.in","r",stdin);
// freopen("girls.out","w",stdout);
n=read(),k=read();
init();
f[]=-;
for(int i=;i<=n;i++)
{
int v;
num[i]=read(),f[i]=read(),v=read();
dis[i][f[i]]=v;
add(f[i],i);
}
initdfs();
dfs();
printf("%d\n",dp[][][k]);
return ;
}

bzoj 1812的更多相关文章

  1. BZOJ 1812: [Ioi2005]riv( 树形dp )

    树背包, 左儿子右兄弟来表示树, dp(x, y, z)表示结点x, x的子树及x的部分兄弟共建y个伐木场, 离x最近的伐木场是z时的最小代价. 时间复杂度O(N^2*K^2) ----------- ...

  2. BZOJ.1812.[IOI2005]Riv 河流(树形背包)

    BZOJ 洛谷 这个数据范围..考虑暴力一些把各种信息都记下来.不妨直接令\(f[i][j][k][0/1]\)表示当前为点\(i\),离\(i\)最近的建了伐木场的\(i\)的祖先为\(j\),\( ...

  3. IOI 2005/bzoj 1812:riv 河流

    Description 几乎整个Byteland王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海.这条大河的入海口处有一 ...

  4. BZOJ1812 [IOI2005]river

    传送门: 很常规的一道树规,转为左儿子右兄弟. 然后$f[node][anc][K]$表示在node节点上,最近的有贡献祖先在anc上,在node的儿子和兄弟上有k个有贡献节点的最优值. 然后得出以下 ...

  5. dp专练

    dp练习. codevs 1048 石子归并 区间dp #include<cstdio> #include<algorithm> #include<cstring> ...

  6. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  7. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  8. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  9. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

随机推荐

  1. vue-axios

    vue axios全攻略   不再继续维护vue-resource,并推荐大家使用 axios 开始,axios 被越来越多的人所了解.本来想在网上找找详细攻略,突然发现,axios 的官方文档本身就 ...

  2. day 11 - 2 装饰器练习

    1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件)要求登录成功一次,后续的函数都无需再输入用户名和密码 FLAG = False def login(func): def inner ...

  3. tomcat BIO / NIO

    BIO NIO ref https://www.jianshu.com/p/76ff17bc6dea http://gearever.iteye.com/blog/1841586

  4. 给tomcat 配置https

    参考以下链接 https://www.cnblogs.com/xiaoliao/p/5778262.html 本人使用环境和版本 tomcat 7.7 阿里云 centos 7还是red hat 浏览 ...

  5. Django学习手册 - 基于requests API验证(一)

    验证需要知道requests提交数据的几种方式: GET 方式: # get 方式,传递数值可以直接通过url传递:(服务端接受 GET) requests.get(url='http://127.0 ...

  6. Hibernate学习(三)

    Hibernate的查询方法(五种) 一.OID查询:按主键查询 --get( ) --load( ) 二.对象导航查询:通过已经查询到的联系人,得到起关联的对象 三.SQL查询 四.HQL查询(** ...

  7. Linux安装JDK(tar)

    我以JDK1.8为例 ⒈下载 https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html ...

  8. C++ 11 snippets , 2

    <1>auto ,initializer_list<T>,auto指向函数指针的简易,和typdef 定义的类型执行函数指针有多复杂. #include <iostrea ...

  9. IPC$横向渗透代码实现

    思路 IPC$横向渗透的方法,也是病毒常用的扩散方法. 1.建立连接 2.复制文件到共享中C$.D$.E$.F$ 3.获取服务器的时间 3.设定计划任务按时间执行 用到的Windows API 建立网 ...

  10. Yara VS2017出现LINK : fatal error LNK1104: 无法打开文件“msvcrt.lib”

    解决方法1 搜索msvcrt.lib所在的路径 C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MS ...