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 web实现综合查询+SQL语句拼接
首先展示图形界: 界面比较简单,但麻雀虽小五脏俱全.因为数据库只有六种数据类型,所以最多添加六个查询框. 测试以下问题: 删除方式是从上往下开始的,如果删除之后会有问题.(后续改进ing) 若干个并且 ...
- F5之LTM入门(转)
原文链接:https://kuaibao.qq.com/s/20180812G02WG200?refer=cp_1026文章来源:企鹅号 - 奕知伴解 什么是负载均衡? 服务器负载均衡器是指设置在一组 ...
- UML-重构
1.重构是什么? 重构是重写或重新构建已有代码的结构化和规律性方法,但不会改变已有代码的外在行为,而是采用一系列少量转换的步骤,并且每一步都结合了重新执行的测试.重构并不是全部推翻原有代码结构. 2. ...
- JDBC<android studio,kotlin>
工具:mysql 5.6.19,mysql-connector-java-5.1.48.jar,android stuido&android studio自带模拟器 1.在mysql数据库中新 ...
- ubuntu---【NVIDIA驱动 + CUDA 安装】不成功时的卸载方式
NVIDIA驱动 与 CUDA 安装不成功时,可以卸载,检查相关问题(配置.兼容性等),重新安装.这里记录一下,卸载方式.
- 单细胞测序|单细胞基因组|单细胞转录组|Gene editing|
单细胞测序 单细胞基因组学 测量理由是单细胞的时间空间特异性. Gene expression&co-expression 比较正常cell与疾病cell,正常organ与疾病organ,看出 ...
- idea代理上网
idea 代理上网 浏览器能够上网,idea无法下载jar 浏览器无法上网则配置浏览器代理 --------- start //------------------------浏览器代理完毕 idea ...
- 设x,y是概率空间(Ω,F,P)上的拟可积随机变量,证明:X=Y a.e 当且仅当 xdp = ydp 对每个A∈F成立。Q: X=Y almost surely iff ∀A∈G∫AXdP=∫AYdP
E{XE{Y|C}}=E{YE{X|C}} 现在有没有适合大学生用的搜题软件呢? https://www.zhihu.com/question/51935291/answer/514312093 ...
- springboot和shiro的整合
直接贴上代码 1. 所需要的jar包 <dependency> <groupId>org.apache.shiro</groupId> <artifactId ...
- Android巩固之事件分发机制
https://www.cnblogs.com/liaojie970/p/5869152.html onTouchEvent是真正用来进行业务逻辑处理的地方,返回true表示已经将该事件消费,返回fa ...