【题解】IOI2005River 河流
一节语文课想出来的玩意儿,调了几个小时……可见细心&好的代码习惯是有多么的重要 (;へ:)
不过,大概竞赛最令人开心的就是能够一点一点的感受到自己的进步吧,一天比一天能够自己想出更多的题,A题之后刹那的欣喜……这些也正是坚持的最大动力。
……矫情了一波还是回到正题上吧:好像这题的正解是多叉树转二叉树?可是我并不会啊。首先我们看到这题的范围非常的小,所以肯定除了爆搜之外的乱搞都OK。(说不定爆搜+超强剪枝啥的也可以?但我没有尝试了……)那我们开始分析一波:动态规划最忌把所有东西都糊在一坨,重在分别状态,所以自然我们第一步需要建立出状态&分析出每一个节点独立的贡献。建立状态我们先采用最自然的想法:dp[u][k]表示u节点下k个节点建立了伐木场的最大贡献。
最大贡献……什么是贡献?正向的统计节点的花费好像不是很容易,不如考虑减少的花费。如果我们在一个节点上建立了伐木场,则该节点向下往叶子上走,遇到的第一个伐木场之间的节点都会运向该伐木场,所节省的成本即为dis[u] * w[v]。那么我们的思路就形成了:dp[u][k] 表示u节点下k个节点建立了伐木场的最大贡献,且强制第k个建立在u节点上。对于每一个u节点而言,我们都遍历一遍它的子树,求出 f 数组,f[u][k] 表示u & u的子树中建立k个伐木场的最大贡献(不强制建在u节点上)。
转移方程:背包求出组合最优解,求f数组时枚举:该节点建伐木场:伐木场数量+1,贡献 + dis[v] * w[v];该节点不建立伐木场:受当前 dp 建立的伐木场的‘管辖’,贡献 + dis[u] * w[v];最关键的地方还是在于将子树状态与父亲状态分离开来,这样就方便进行状态的转移了。
虽然感觉复杂度非常的高:达到了\(n^2\)(单单考虑dfs)的级别,然而在luogu上rank1?大概是玄学……
#include <bits/stdc++.h>
using namespace std;
#define maxn 105
int n, K, cnp = 1, ans, head[maxn], w[maxn];
int dis[maxn], size[maxn];
int dp[maxn][maxn], f[maxn][maxn]; struct edge
{
int to, co, last;
}E[maxn]; int read()
{
int x = 0, k = 1;
char c;
c = getchar();
while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * k;
} void add(int u, int v, int w)
{
E[cnp].to = v, E[cnp].co = w;
E[cnp].last = head[u], head[u] = cnp ++;
} void gmax(int &a, int b) { a = a > b ? a : b; } void DP(int u, int gra)
{
f[u][0] = dis[gra] * w[u];
for(int i = head[u]; i; i = E[i].last)
{
DP(E[i].to, gra);
for(int j = min(size[u], K); ~j; j --)
{
int lim = min(size[E[i].to], j);
for(int k = 0; k <= lim; k ++)
gmax(f[u][j], f[E[i].to][k] + f[u][j - k]);
}
}
for(int j = size[u]; j; j --) gmax(f[u][j], dp[u][j]);
} void dfs(int u)
{
size[u] = 1;
for(int i = head[u]; i; i = E[i].last)
{
int v = E[i].to;
dis[v] = E[i].co + dis[u];
dfs(v); size[u] += size[v];
}
dp[u][0] = 0, ans += dis[u] * w[u];
memset(f, 0, sizeof(f));
for(int i = head[u]; i; i = E[i].last)
{
DP(E[i].to, u);
for(int j = min(K, size[u]); ~j; j --)
for(int k = 0; k <= min(j, size[E[i].to]); k ++)
gmax(dp[u][j], f[E[i].to][k] + dp[u][j - k]);
}
for(int i = min(size[u], K); i; i --) dp[u][i] = dp[u][i - 1] + dis[u] * w[u];
} int main()
{
n = read(), K = read();
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i ++)
{
w[i] = read(); int v = read(), z = read();
add(v, i, z);
}
dfs(0); int tem = 0;
memset(f, 0, sizeof(f));
for(int i = head[0]; i; i = E[i].last)
{
DP(E[i].to, 0);
for(int j = min(size[0], K); ~j; j --)
{
int lim = min(size[E[i].to], j);
for(int k = 0; k <= lim; k ++)
gmax(f[0][j], f[E[i].to][k] + f[0][j - k]);
}
}
for(int i = 1; i <= size[0]; i ++) tem = max(tem, f[0][i]);
printf("%d\n", ans - tem);
return 0;
}
【题解】IOI2005River 河流的更多相关文章
- LuoguB2001 入门测试题目 题解
Update \(\texttt{2021.7.3}\) 经测试,本题 \(a,b\) 范围在 long long,对代码进行了修改,并修改一些笔误,更新了数据范围. \(\texttt{2021.7 ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
随机推荐
- 封装localstorage方法
//封装操作localstorage本地存储的方法 var storage = { //存储 set(key, value) { localStorage.setItem(key, JSON.stri ...
- 介绍几个PHP 自带的加密解密函数
PHP 自带的加密解密函数 目前经常使用的加密函数有:md5(), sha1(), crypt(), base64_encode(), urlencode() . 其中 md5(), sha1(), ...
- 解决pycharm报错:AttributeError: module 'pip' has no attribute 'main'
找到pycharm安装目录下 helpers/packaging_tool.py文件,找到如下代码: def do_install(pkgs): try: import pip except Impo ...
- django之多表查询
一.创建模型 在Models创建如下模型: from django.db import models # Create your models here. # 用了OneToOneField和Fore ...
- 责任链模式的使用-Netty ChannelPipeline和Mina IoFilterChain分析
本文来自网易云社区 作者:乔安然 1. Chain of Responsiblity 定义: 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条链,并沿着这条链 ...
- IOException: win32 io returned 267. Path:
unity3d在导出android项目时出现了这个错误,找了一圈也没找到原因,最后把项目名中空格去掉后OK了,坑啊!!!!
- 使用hibernate连接Oracle时的权限问题
在使用hibernate对象关系映射连接和创建表的时候,会涉及到很多权限问题,有些数据库管理会将权限设的很细,我们可以根据后台日志错误和异常信息作出判断. 比如下图所示这个错误(这是我在给银行投产系统 ...
- 【java并发编程实战】第五章:基础构建模块
1.同步容器类 它们是线程安全的 1.1 vector和hashtable. 和Collections.synchronizeXxx()一样.实现方式就是在每个方法里面加入synchronize代码块 ...
- python 基础篇 13 迭代器与生成器
13. 前⽅⾼能-迭代器和⽣成器本节主要内容:1. 迭代器2. ⽣成器 ⼀. 迭代器我们之前⼀直在⽤可迭代对象进⾏迭代操作. 那么到底什么是可迭代对象. 本⼩节主要讨论可迭代对象. ⾸先我们先回顾⼀下 ...
- HDFS伪分布式
(一).HDFS shell操作 以上已经介绍了如何搭建伪分布式的Hadoop,既然环境已经搭建起来了,那要怎么去操作呢?这就是本节将要介绍的内容: HDFS自带有一些shell命令,通过这些命令我们 ...