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$ 求最大节点集权值, ...
随机推荐
- 编写软件动态加载NT式驱动
NT式设备驱动程序的动态加载主要是由服务控制管理程序(Service Control Manager,即SCM)系统组件来完成的. Windwos服务可以在系统启动时加载,用户也可以按需在服务控制平台 ...
- 对比Node.js和Python 帮你确定理想编程解决方案!
世上没有最好的编程语言.有些编程语言比其他编程语言用于更具体的事情.比如,你可能需要移动应用程序,网络应用程序或更专业化的系统,则可能会有特定的语言.但是我们暂时假设你需要的是一个相对来说比较简单的网 ...
- MySQL视图和事务
视图的操作 ...
- Thread--线程工作万花筒
线程工作内存图. 线程状态.
- JavaScript—原生轮播和无缝滚动
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- shell的一些一句话东西
shell的一些一句话东西 2010-09-10 11:22:58| 分类: linux shell | 标签:shell linux |举报|字号 订阅 time -p [程序] 可 ...
- vue验证时间范围
验证时间范围 type="daterange" <DatePicker class="formItem" :size="size" v ...
- JDK11 JAVA11下载安装与快速配置环境变量教程
https://blog.csdn.net/weixin_40928253/article/details/83590136 1.到Oracle官网下载jdk11,并安装.搜索“jdk",选 ...
- PAT Basic 1104 数字⿊洞 (20) [数学问题-简单数学]
题目 给定任⼀个各位数字不完全相同的4位正整数,如果我们先把4个数字按⾮递增排序,再按⾮递减排序,然后⽤第1个数字减第2个数字,将得到⼀个新的数字.⼀直重复这样做,我们很快会停在有"数字⿊洞 ...
- PAT Basic 1070 结绳(25) [排序,贪⼼]
题目 给定⼀段⼀段的绳⼦,你需要把它们串成⼀条绳.每次串连的时候,是把两段绳⼦对折,再如下图所示套接在⼀起.这样得到的绳⼦⼜被当成是另⼀段绳⼦,可以再次对折去跟另⼀段绳⼦串连.每次串 连后,原来两段绳 ...