洛谷P3177||bzoj4033 [HAOI2015]树上染色
根本不会做。。。
上网查了题解,发现只要在状态定义的时候就考虑每一条边全局的贡献就好了?
考虑边的贡献和修改状态定义我都想到了,然而并不能想到要结合起来
ans[i][j]表示i子树中选j个黑色节点,最大的贡献和
容易知道:每一条边的贡献为 长度*(边一侧的白点数*边另一侧的白点数+边一侧的黑点数*边另一侧的黑点数)
可以发现,如果已经确定一棵子树中选多少个黑点,那么这棵子树的根到其父亲的连边的贡献可以直接确定
考虑向一棵树的根节点(u)下再加入一棵子树(v)时的转移:sz[u]表示u子树的节点个数
$ans[u][k]=max\{ans[u][i]+ans[v][j]+dis(u,v)*(j*(K-j)+(sz[v]-j)*(n-sz[v]-K+j))\}(k=i+j)$
要构建一棵树,可以先构建完所有以根节点的某个子节点为根的子树,然后再依次将子树与根节点连上边。
复杂度好像是n^3的?事实上只要改一下循环的上界就n^2了。转移某个子树时,i上界为之前已经转移过的子树size和 + 1(根节点自身),j上界为目标子树size
可以发现,树上每一对点对刚好产生1次转移(在lca处产生),因此总复杂度等于总点对数是n^2的
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
struct E
{
ll to,nxt,d;
}e[];
ll f1[],ne;
ll ans[][];
ll sz[];
ll tmp[];
ll n,K;
void dfs(ll u,ll fa)
{
ans[u][]=ans[u][]=;sz[u]=;
ll i,j;
for(ll v,k=f1[u];k;k=e[k].nxt)
if(e[k].to!=fa)
{
v=e[k].to;
dfs(v,u);
memset(tmp,,sizeof(ll)*(sz[u]+sz[v]+));
for(i=sz[u];i>=;--i)
{
for(j=sz[v];j>=;--j)
{
if(K>=j&&n-sz[v]-K+j>=)
{
tmp[i+j]=max(tmp[i+j],ans[u][i]+ans[v][j]
+e[k].d*(j*(K-j)+(sz[v]-j)*(n-sz[v]-K+j)));
}
}
}
for(i=;i<=sz[u]+sz[v];++i)
ans[u][i]=tmp[i];
sz[u]+=sz[v];
}
//printf("1t%lld\n",u);
//for(i=0;i<=sz[u];i++)
// printf("%lld %lld\n",i,ans[u][i]);
}
int main()
{
ll i,x,y,z;
memset(ans,,sizeof(ans));
scanf("%lld%lld",&n,&K);
for(i=;i<n;++i)
{
scanf("%lld%lld%lld",&x,&y,&z);
e[++ne].to=y;e[ne].nxt=f1[x];f1[x]=ne;e[ne].d=z;
e[++ne].to=x;e[ne].nxt=f1[y];f1[y]=ne;e[ne].d=z;
}
dfs(,);
printf("%lld",ans[][K]);
return ;
}
洛谷P3177||bzoj4033 [HAOI2015]树上染色的更多相关文章
- BZOJ4033 HAOI2015 树上染色 【树上背包】
BZOJ4033 HAOI2015 树上染色 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白 ...
- [BZOJ4033][HAOI2015]树上染色(树形DP)
4033: [HAOI2015]树上染色 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2437 Solved: 1034[Submit][Stat ...
- BZOJ4033: [HAOI2015]树上染色(树形DP)
4033: [HAOI2015]树上染色 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 3461 Solved: 1473[Submit][Stat ...
- [bzoj4033][HAOI2015]树上染色_树形dp
树上染色 bzoj-4033 HAOI-2015 题目大意:给定一棵n个点的树,让你在其中选出k个作为黑点,其余的是白点,收益为任意两个同色点之间距离的和.求最大收益. 注释:$1\le n\le 2 ...
- 【题解】 bzoj4033: [HAOI2015]树上染色* (动态规划)
bzoj4033,懒得复制,戳我戳我 Solution: 定义状态\(dp[i][j]\)表示\(i\)号节点为根节点的子树里面有\(j\)个黑色节点时最大的贡献值 然后我们要知道的就是子节点到根节点 ...
- 【树形背包】bzoj4033: [HAOI2015]树上染色
仔细思考后会发现和51nod1677 treecnt有异曲同工之妙 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 ...
- [BZOJ4033]:[HAOI2015]树上染色(树上DP)
题目传送门 题目描述 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白色.将所有点染色后,你会获得黑点两两之间的距离加 ...
- BZOJ4033 [HAOI2015]树上染色 【树形dp】
题目 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 将其他的N-K个点染成白色.将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间 ...
- BZOJ4033 [HAOI2015]树上染色
本来是考虑, $ f[x][i][0/1] $ 表示 $ x $ 子树中有$i$个黑点,且 $ x $ 是白点/黑点.但是这里的答案是要统计不同的子树的贡献的.所以就gg了. 看了题解. 应该是要设$ ...
随机推荐
- valid No such filter: 'drawtext'"
libfreetype is missing. You'll have to rebuild FFmpeg with this library or disable overlays. --enabl ...
- phpcms v9中的$CATEGORYS栏目数组
首先 如果不能用$CATEGORYS这个数组或掉不出来内容应加入 $CATEGORYS = getcache('category_content_1','commons'); 1.用途 $CATEGO ...
- WinThruster中文版破解方法(注册表无伤清理工具)
每次卸载完软件,都会有注册表残余垃圾,久而久之电脑会越来越慢,winThruster可以检测出系统无用注册表,并删除. 1.解压文件,安装Setup_WinThruster_2015.exe文件. 2 ...
- C# 获取QQ群数据的实现
一,分析 1,群数据获取 当访问http://qun.qq.com/air/#mygroup我们通过Fiddler可以查看到QQ群列表是从http://qun.qq.com/air/group/min ...
- poj 2069 Super Star —— 模拟退火
题目:http://poj.org/problem?id=2069 仍是随机地模拟退火,然而却WA了: 看看网上的题解,都是另一种做法——向距离最远的点靠近: 于是也改成那样,竟然真的A了...感觉这 ...
- POJ2406(next原理理解)
Power Strings Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 40448 Accepted: 16828 D ...
- React.js:template
ylbtech-React.js: 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 作者:ylbtech出处:http://ylbtec ...
- 四、mysql数据常用命令
1.显示mysql中所有数据库的名称,show databases; 2.访问某个数据库,use database_name; 3.显示当前数据库中所有表的名称,show tables; 4.查看当前 ...
- Python2.7 urlparse学习
urlparse模块主要是把url拆分为6部分,并返回元组.并且可以把拆分后的部分再组成一个url.主要有函数有urljoin.urlsplit.urlunsplit.urlparse等. urlpa ...
- java 中判断字符串相等
今天写Java代码时遇到一个问题,就是关于判断两个字符串是否相等的问题.(刚尝试用SSH框架) 在大多编程中,通常比较两个字符串是否相同的表达式是“==”,但在java中不能这么写.在java中,用的 ...