题目链接


题目大意:

就是一棵5e35e35e3的树,可以选择一些点,放上基站,如果uuu上的基站价值为ddd,那么距离uuu小于等于ddd的点都会被覆盖,问使得整棵树被覆盖需要的最小价值。


解题思路:

  1. 一开始我是这么想树形dp的 dp[i][j]表示覆盖完i子树并且i节点放置权值为j的覆盖站的所需要的最小价值dp[i][j]表示覆盖完i子树并且i节点放置权值为j的覆盖站的所需要的最小价值dp[i][j]表示覆盖完i子树并且i节点放置权值为j的覆盖站的所需要的最小价值

  2. 但是这里有两个问题就是如果你是有根树:你每个点的放置一个权值为www的信号站,不仅会覆盖到儿子节点,也会覆盖到祖先节点,这样dpdpdp不容易实现,因为你不知道它向上影响了多远

  3. 那么我们为什么不把那个影响距离带到dpdpdp方程里面去呢?

  4. dp[u][j]表示覆盖完u这个子树并且能够覆盖到所有向上距离它≤j所有点的最小代价是多少?dp[u][j]表示覆盖完u这个子树并且能够覆盖到所有向上距离它\leq j所有点的最小代价是多少?dp[u][j]表示覆盖完u这个子树并且能够覆盖到所有向上距离它≤j所有点的最小代价是多少?

  5. 那么我们知道向上影响距离是jjj无非两种情况就是
    (1):在u这个位置直接放置权值为jjj的基站
    (2):子树传递影响上去

  6. 对于子树直接放置权值为jjj的基站我们知道它的影响是两个方向的有儿子也有祖先:那么根据贪心原理dp[u][j]=j+g[u][j+1],g[u][j+1]:覆盖距离u距离≥j的所有dp[u][j]=j+g[u][j+1],g[u][j+1]:覆盖距离u距离\ge j的所有dp[u][j]=j+g[u][j+1],g[u][j+1]:覆盖距离u距离≥j的所有儿子节点所需要的最小代价(注意这里是只有儿子)

  7. 如果是子树传递上去的呢?
    dp[u][j]=min{dp[sonu][j+1]+(g[u][j+1]−g[sonu][j])}dp[u][j]=min\{dp[son_u][j+1]+(g[u][j+1]-g[son_u][j])\}dp[u][j]=min{dp[sonu​][j+1]+(g[u][j+1]−g[sonu​][j])}
    为啥要减掉g[sonu][j]g[son_u][j]g[sonu​][j]因为贡献重复计算了

  8. 那么ggg数组怎么算呢?很好算的g[u][i]+=g[sonu][i−1]g[u][i]+=g[son_u][i-1]g[u][i]+=g[sonu​][i−1]

  9. 注意点1:就是dp[u][0]=0+g[u][1]dp[u][0]=0+g[u][1]dp[u][0]=0+g[u][1]这是不合法的因为实际上并没有包含到uuu节点,那么dp[u][0]dp[u][0]dp[u][0]只能算第二种情况就是子树传递贡献上去!!

  10. 注意点2:就是实际上dp[u][i+1]dp[u][i+1]dp[u][i+1]是对dp[u][i]dp[u][i]dp[u][i]有贡献影响的,因为覆盖范围≥i+1\ge i+1≥i+1肯定也≥i\ge i≥i,ggg数组同理也是g[u][i−1]g[u][i-1]g[u][i−1]对g[u][i]g[u][i]g[u][i]是用贡献的因为距离≤i−1\leq i-1≤i−1肯定也≤i\leq i≤i

  11. 注意点3:g[u][0]=dp[u][0]g[u][0]=dp[u][0]g[u][0]=dp[u][0]


AC code

#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define f first
#define s second
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 9;
const int maxn = 5010;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x) {x = 0;char ch = getchar();ll f = 1;while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {read(first);read(args...);
}
int n, lim = 5000;
vector<int> G[maxn];
int dp[maxn][maxn]; // dp[u][j] 表示覆盖完u这个子树并且覆盖了上面所有距离<=j的祖先节点最小费用
int g[maxn][maxn]; // g[u][i] 表示覆盖了距离u >= i的所有节点所需要的最小费用
void dfs(int u, int fa) {int min_son = -1;for(auto it : G[u]) {if(it == fa) continue;dfs(it,u);for(int i = 1; i <= lim; ++ i) g[u][i] += g[it][i-1];if(min_son == -1 || dp[it][1] < dp[min_son][1])min_son = it;}if(G[u].size() == 1 && u != 1) dp[u][0] = 1; // 叶子节点为1else dp[u][0] = dp[min_son][1] + g[u][1] - g[min_son][0];dp[u][lim] = INF;// 把边界设置成无穷大for(int i = lim - 1; i >= 1; -- i) {dp[u][i] = g[u][i+1] + i;for(auto it : G[u]) if(it != fa) {dp[u][i] = min(dp[it][i+1]-g[it][i]+g[u][i+1],dp[u][i]);}} // 处理一下同层之间的贡献for(int i = lim-1; i >= 0; -- i) dp[u][i] = min(dp[u][i],dp[u][i+1]); g[u][0] = dp[u][0]; // g的边界for(int i = 1; i <= lim; ++ i) g[u][i] = min(g[u][i],g[u][i-1]);
}int main() {IOS;cin >> n;for(int i = 1; i < n; ++ i) {int u, v;cin >> u >> v;G[u].push_back(v);G[v].push_back(u);}   dfs(1,0);cout << g[1][0];return 0;
}

树形dp ---- gym101667 A(贪心 + 树形dp + 两个dp方程组维护)相关推荐

  1. Parsa‘s Humongous Tree(贪心+树形dp)

    今天来给大家分享一道考察贪心的题目: Parsa has a humongous tree on nn vertices. On each vertex v he has written two in ...

  2. 【POJ - 1947】Rebuilding Roads (树形dp,背包问题,树形背包dp)

    题干: The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1. ...

  3. 详解吉首大学第九届“新星杯”G芒砀山的神秘数字 两种dp

    题目链接 题目大意就是给一个长的字符串a和一个短的字符串b,询问a里面有多少个序列是大于b的. 这里我们分两步来处理,就是我们先算出a中的序列长度和b一样的.因为显然答案是由序列长度一样的数量+序列长 ...

  4. dp 扔鸡蛋_使用动态编程(DP)的鸡蛋掉落问题

    dp 扔鸡蛋 Problem statement: You are given N floor and K eggs. You have to minimize the number of times ...

  5. 牛客 - 树上求和(贪心+树形dp)

    题目链接:点击查看 题目大意:给出一棵树,现在要求给每条边赋上 0 ~ n - 1 的值,且不重复,规定每条路径 ( u , v ) 的权值和为其简单路径上的边权之和,而整棵树的权值和为 所有简单路径 ...

  6. 2020牛客多校9:B. Groundhog and Apple Tree(树形DP + 分类讨论 + 贪心)

    题目大意:有一棵苹果树,每个节点有一个苹果,吃掉 uuu 点的苹果能获得 aua_uau​点 HP,经过第 iii 条边需要消耗 wiw_iwi​ HP,在原地等待一秒可以获得 111 HP,每条边只 ...

  7. $bzoj1060-ZJOI2007$ 时态同步 贪心 树形$dp$

    题面描述 小\(Q\)在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数字\(1,2,3-.\)进行标号.电路板的各个节点由若干不相交的导线相连接,且对于电路 ...

  8. 洛谷 P5536 【XR-3】核心城市(贪心 + 树形 dp 寻找树的中心)

    [XR-3]核心城市 题目描述 X 国有 nnn 座城市,n−1n - 1n−1 条长度为 111 的道路,每条道路连接两座城市,且任意两座城市都能通过若干条道路相互到达,显然,城市和道路形成了一棵树 ...

  9. 树形dp ---- C. Karen and Supermarket(子树选择类型dp + 注意dp更新顺序)

    题目链接 题目大意: 解题思路: 如果你要打折某个商品那么它到1的路径上所以点都要买并且打折 有点像树上背包了,我们对于最大购买量做dp不是很好dp,但是我们可以用背包的思想就是:我们可以求出在买xx ...

最新文章

  1. Redis线程模型的前世今生
  2. Oracle维护数据完整性——约束
  3. 二叉树层序遍历递归与非递归_二叉树的遍历「递归、非递归」以及自己的感受
  4. 惊爆漏洞ShopEX4.8.5隐患漏洞,最终解决方法ShopEX4.8.5安装完成后打开显示:Access denied by install.lock...
  5. html在线布局,HTML 布局
  6. php对象数字属性,PHP获取对象的纯数字属性
  7. 【原】数据分析/数据挖掘/机器学习---- 必读书目
  8. 用Android自带的signapk.jar + .x509.pem + .pk8签名应用程序 - anfflee
  9. mysql 拼音首字母_MySQL拼音首字母查询
  10. qt 部署 错误_Qt 5.9 安装过程报错现象及解决方案
  11. Loongson2f_龙芯逸珑8089A_扩容硬盘安装debian8(sd卡扩容)
  12. {dede-list flag='h'}DedeCMS支持flag标签解决办法
  13. 什么是ISCSI?ISCSI又能干什么呢?
  14. python爬虫作业帮_2020高校邦《网络数据采集与Python爬虫【带实验】》课后作业参考答案2020知到《PPT创意动画》单选题答案...
  15. u盘server2012服务器系统安装,如何安装原版Windows server 2012?U盘安装原版Windows server 2012方法...
  16. Bitmap、CBitmap、HBITMAP以及BITMAP的相互转换
  17. 在不规则四边形的内部随机一个点
  18. 微信小程序记录与项目实践
  19. 统计学 统计值判断标准
  20. 外国官方网站下载文件速度缓慢

热门文章

  1. 流量控制与可靠传输机制
  2. Tomcat版本不同,功能区别也是很大!
  3. 软考网络工程师身份证忘记领取啦怎么办
  4. 用于道路目标检测的少镜头学习
  5. 深度学习中的图像分割:方法和应用
  6. 从深度图到点云的构建方式
  7. 第二项目AIaisell(易销宝)
  8. SFB 项目经验-09-用Lync 2013或Skype for Business 2015抢火车票
  9. 分布式团队面临的五大问题及解决办法
  10. Nimbus/Supervisor本地目录结构