洛谷P3177

bzoj4033

根本不会做。。。

上网查了题解,发现只要在状态定义的时候就考虑每一条边全局的贡献就好了?

考虑边的贡献和修改状态定义我都想到了,然而并不能想到要结合起来

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]树上染色的更多相关文章

  1. BZOJ4033 HAOI2015 树上染色 【树上背包】

    BZOJ4033 HAOI2015 树上染色 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白 ...

  2. [BZOJ4033][HAOI2015]树上染色(树形DP)

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2437  Solved: 1034[Submit][Stat ...

  3. BZOJ4033: [HAOI2015]树上染色(树形DP)

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 3461  Solved: 1473[Submit][Stat ...

  4. [bzoj4033][HAOI2015]树上染色_树形dp

    树上染色 bzoj-4033 HAOI-2015 题目大意:给定一棵n个点的树,让你在其中选出k个作为黑点,其余的是白点,收益为任意两个同色点之间距离的和.求最大收益. 注释:$1\le n\le 2 ...

  5. 【题解】 bzoj4033: [HAOI2015]树上染色* (动态规划)

    bzoj4033,懒得复制,戳我戳我 Solution: 定义状态\(dp[i][j]\)表示\(i\)号节点为根节点的子树里面有\(j\)个黑色节点时最大的贡献值 然后我们要知道的就是子节点到根节点 ...

  6. 【树形背包】bzoj4033: [HAOI2015]树上染色

    仔细思考后会发现和51nod1677 treecnt有异曲同工之妙 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 ...

  7. [BZOJ4033]:[HAOI2015]树上染色(树上DP)

    题目传送门 题目描述 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白色.将所有点染色后,你会获得黑点两两之间的距离加 ...

  8. BZOJ4033 [HAOI2015]树上染色 【树形dp】

    题目 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 将其他的N-K个点染成白色.将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间 ...

  9. BZOJ4033 [HAOI2015]树上染色

    本来是考虑, $ f[x][i][0/1] $ 表示 $ x $ 子树中有$i$个黑点,且 $ x $ 是白点/黑点.但是这里的答案是要统计不同的子树的贡献的.所以就gg了. 看了题解. 应该是要设$ ...

随机推荐

  1. valid No such filter: 'drawtext'"

    libfreetype is missing. You'll have to rebuild FFmpeg with this library or disable overlays. --enabl ...

  2. phpcms v9中的$CATEGORYS栏目数组

    首先 如果不能用$CATEGORYS这个数组或掉不出来内容应加入 $CATEGORYS = getcache('category_content_1','commons'); 1.用途 $CATEGO ...

  3. WinThruster中文版破解方法(注册表无伤清理工具)

    每次卸载完软件,都会有注册表残余垃圾,久而久之电脑会越来越慢,winThruster可以检测出系统无用注册表,并删除. 1.解压文件,安装Setup_WinThruster_2015.exe文件. 2 ...

  4. C# 获取QQ群数据的实现

    一,分析 1,群数据获取 当访问http://qun.qq.com/air/#mygroup我们通过Fiddler可以查看到QQ群列表是从http://qun.qq.com/air/group/min ...

  5. poj 2069 Super Star —— 模拟退火

    题目:http://poj.org/problem?id=2069 仍是随机地模拟退火,然而却WA了: 看看网上的题解,都是另一种做法——向距离最远的点靠近: 于是也改成那样,竟然真的A了...感觉这 ...

  6. POJ2406(next原理理解)

    Power Strings Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 40448   Accepted: 16828 D ...

  7. React.js:template

    ylbtech-React.js: 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   作者:ylbtech出处:http://ylbtec ...

  8. 四、mysql数据常用命令

    1.显示mysql中所有数据库的名称,show databases; 2.访问某个数据库,use database_name; 3.显示当前数据库中所有表的名称,show tables; 4.查看当前 ...

  9. Python2.7 urlparse学习

    urlparse模块主要是把url拆分为6部分,并返回元组.并且可以把拆分后的部分再组成一个url.主要有函数有urljoin.urlsplit.urlunsplit.urlparse等. urlpa ...

  10. java 中判断字符串相等

    今天写Java代码时遇到一个问题,就是关于判断两个字符串是否相等的问题.(刚尝试用SSH框架) 在大多编程中,通常比较两个字符串是否相同的表达式是“==”,但在java中不能这么写.在java中,用的 ...