F. Maximum Weight Subset(贪心or树形dp解法)
题:https://codeforces.com/contest/1249/problem/F
题意:给一颗树,边权为1,节点有点权,问取到一个点集,俩俩之间路径超过k,是点权和最大
思路:贪心地取点,先将点按照深度经行排序,每一次,取一个点权大于0的点,然后对于这个点bfs出去的路径小于k的点减去当前点的a[u],然后将a[i]加入到ans中
#include<bits/stdc++.h>
using namespace std;
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=b;i>=a;i--)
#define pb push_back
const int M=;
int deep[M],vis[M],a[M],b[M],k,n;
vector<int>g[M];
void dfs(int u,int f){
deep[u]=deep[f]+;
for(int i=;i<g[u].size();i++){
int v=g[u][i];
if(v!=f){
dfs(v,u);
}
}
}
bool cmp(int x,int y){
return deep[x]>deep[y];
}
struct node{
int val,st;
};
int bfs(int st){
queue<node>que;
node s;
s.val=st;
s.st=;
que.push(s);
memset(vis,,sizeof(vis));
int c=a[st];
while(!que.empty()){
node u=que.front();
vis[u.val]=;
a[u.val]-=c;
que.pop();
if(u.st!=k){
for(int i=;i<g[u.val].size();i++){
int v=g[u.val][i];
if(!vis[v]){
node p;
p.val=v;
p.st=u.st+;
que.push(p);
}
}
} }
return c;
}
int main(){ scanf("%d%d",&n,&k);
fo(i,,n)
scanf("%d",&a[i]);
fo(i,,n-){
int x,y;
scanf("%d%d",&x,&y);
g[x].pb(y);
g[y].pb(x);
}
dfs(,);
fo(i,,n)b[i]=i;
sort(b+,b++n,cmp);
int ans=;
fo(i,,n)
if(a[i]>)
ans+=bfs(i);
cout<<ans<<endl;
return ;
}
树形dp做法
dp[u][i]表示以u的子树中被选的点离u最近距离是i的最大权值和;
对当前节点,我们分取和不取的情况;
取的情况:那么当前点的子树对当前点的贡献肯定就是∑dp[v][k];
不取的情况:那么我们就既要保证子树之间的距离要大于k,又要满足子树对当前节点距离为i的贡献。若一个子树取了距离为i-1,那么就要保证其他子树取的距离都要大于k-i。
当平衡的时候我们得到一个式子k-(k-i+1) = i-1,所以要在k-i和i-1中取最大值,作为要对当前节点u做贡献的v的距离j,也就是dp[v][j]。
分析一下,当j取i-1的时候要求其他子树与当前节点u的距离要大于k-(i-1),因为在上面 j 已经取了(k-i)和(i-1)的最大值,所以不用考虑其他,直接把dp[v][j]加上去;
当 j 取k-i时,我们发现实际上,k-i一定比i-1更深,所以dp[v][k-1]<=dp[v][i-1],所以取值上虽然取的时深度为k-i深度的值,此时我们可以假想取的时i-1的位置,
所以就满足了距离为 i 的限制,接着,又因为只是要大于k而已,我们取的深度明显大于k一些,所以为了最大化答案,就取max(dp[v][i-1]-dp[v][j])。只是一个子树达到了 i-1 ,
这并不会影响俩俩子树之间距离大于k的事实
#include<bits/stdc++.h>
using namespace std;
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=b;i>=a;i--)
#define pb push_back
const int M=;
vector<int>g[M];
int n,k;
int a[M];
int dp[M][M];//dp[u][i]表示以u的子树中被选的点离u最近距离是i的最大权值和
void dfs(int u,int f){
for(int i=;i<g[u].size();i++){
int v=g[u][i];
if(v==f)
continue;
dfs(v,u);
}
//cout<<"!!"<<endl;
for(int i=n-;i>=;i--){
if(i==){//u不取的情况
for(int p=;p<g[u].size();p++){
int v=g[u][p];
if(v==f)
continue;
dp[u][i]+=dp[v][k];
}
dp[u][i]+=a[u];
}
else{
int j=max(i-,k-i);
int tot=,mx=;
for(int p=;p<g[u].size();p++){
int v=g[u][p];
if(v==f)
continue;
tot+=dp[v][j];
mx=max(mx,dp[v][i-]-dp[v][j]);
}
dp[u][i]=tot+mx;
}
dp[u][i]=max(dp[u][i],dp[u][i+]);
}
}
int main(){
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
for(int x,y,i=;i<n;i++){
scanf("%d%d",&x,&y);
g[x].pb(y);
g[y].pb(x);
}
dfs(,);
printf("%d\n",dp[][]);
return ;
}
F. Maximum Weight Subset(贪心or树形dp解法)的更多相关文章
- Codeforces 1249F Maximum Weight Subset (贪心)
题意 在一颗有点权的树上,选若干个点,使得这些点两两距离大于k,且点权和最大 思路 贪心的取比较大的值即可 将所有点按照深度从大到小排序,如果当前点点权\(a[i]\)大于0,则将距离为k以内的所有点 ...
- Codeforces 1249 F. Maximum Weight Subset
传送门 设 $f[x][i]$ 表示 $x$ 的子树中,离 $x$ 最近的选择的节点距离为 $i$ 的合法方案的最大价值 设 $val[x]$ 表示节点 $x$ 的价值,首先有 $f[x][0]=va ...
- CF1249F Maximum Weight Subset
CF1249F Maximum Weight Subset 洛谷评测传送门 题目描述 You are given a tree, which consists of nn vertices. Reca ...
- 求树的最大独立集,最小点覆盖,最小支配集 贪心and树形dp
目录 求树的最大独立集,最小点覆盖,最小支配集 三个定义 贪心解法 树形DP解法 (有任何问题欢迎留言或私聊&&欢迎交流讨论哦 求树的最大独立集,最小点覆盖,最小支配集 三个定义 最大 ...
- 【CF1249F】Maximum Weight Subset(贪心)
题意:给定一棵n个点带点权的树,要求从中选出一个点集,使得这些点两两之间距离都大于K,求最大点权和 n,K<=2e2,1<=a[i]<=1e5 思路:树形DP显然可做,极限是n方,然 ...
- P2279 [HNOI2003]消防局的设立 贪心or树形dp
题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状 ...
- bzoj 2067: [Poi2004]SZN【贪心+二分+树形dp】
第一问就是Σ(deg[u]-1)/2+1 第二问是二分,判断的时候考虑第一问的贪心规则,对于奇度数的点,两两配对之后一条延伸到上面:对于欧度数的点,两两配对或者deg[u]-2的点配对,然后一条断在这 ...
- Strategic game树形DP解法(Poj1463,Uva1292)
已经写过本题用二分图的做法,见这儿. 本题的图是一棵树,求最小点覆盖也可以用树形DP的做法. 定义状态f[0/1][u]表示以u为根的子树,u选取/不选最少需要选取多少点来覆盖. 显然 f[0][u] ...
- codeforces#1249F. Maximum Weight Subset(树上dp)
题目链接: http://codeforces.com/contest/1249/problem/F 题意: 一棵树的每个节点有个权值,选择一个节点集,使得任意点对的距离大于$k$ 求最大节点集权值, ...
随机推荐
- Java底层魔术类Unsafe用法简述
1 引子 Java中没有指针,不能直接对内存地址的变量进行控制,但Java提供了一个特殊的类Unsafe工具类来间接实现.Unsafe主要提供一些用于执行低级别.不安全操作的方法,如直接访问系统内存资 ...
- Java 性能优化:面向对象及基础类型使用优化
性能优化是个大筐,很多东西都能往里面装.虽说性能优化的具体方面比较多,但万丈高楼从地起,这里还是从Java最基本的一些入门知识相关的使用优化进行一些做些总结和建议.如何连最基本的API使用都不会,或不 ...
- CountUp.js 数字跳转效果小插件
CountUp.js 实现数字跳转效果的小插件 //调用方法 const easingFn = function (t, b, c, d) { var ts = (t /= d) * t; var ...
- clion之CMakeLists的学习
什么是CMake CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程).他能够输出各种各样的makefile或者project文件,能测试编译器所支持的" ...
- mysql 启动报错Host name could not be resolved解决办法
mysql 启动报错信息如下: [root@xxx ~]# 2018-01-26 17:06:35 33 [Warning] Host name 'bogon' could not be resolv ...
- Python—二叉树数据结构
二叉树 简介: 二叉树是每个结点最多有两个子树的树结构.通常子树被称作“左子树”(left subtree)和“右子树”(right subtree). 二叉树二叉树的链式存储: 将二叉树的节点定义为 ...
- Jetson TX2入门学习之Ubuntu默认密码
在使用TX2开发板时进行软件更新时需要身份验证,TX2默认有两个登录身份,一个是ubuntu 一个是nvidia 登录其中的哪一个都可以更新 两个身份的密码和登录名是一样的用户:ubuntu 密码 ...
- 1. react 编程实践 俄罗斯方块-需求分析
1. 需求分析 俄罗斯方块的要素 界面展示 定时刷新 键盘响应 方块模型 游戏规则 俄罗斯方块 比 "电商购物车" 好在哪? 业务比较简单, 人人都了解, 不需要过多前置知识 技术 ...
- 31. docker swarm 通过 service 部署 wordpress
1. 创建 一个 overlay 的网络 driver docker network create -d overlay demo 查看网络列表 docker network ls 2. 创建mysq ...
- Redis_大保健
Redis redis命令参考网址: http://doc.redisfans.com/ redis主从: 集群:一组通过网络连接的计算机,共同对外提供服务,像一个独立的服务器. 一.简介 nosql ...