加权树

题意:

思路:

  • 可以发现,除了单独两个点一条边的情况,这两个点都赋值为 1,都是 good,其他情况下,树中任意相邻两点不可能同时都是 good。画下图就能看出来。当时完全没往这方面想…

  • 这就启发我们,去维护一个树上最大独立集(最大点集同时点集中的点之间没有边)

  • 这完全可以用 树形dp 的思想去维护,用 dp[i][2]dp[i][2]dp[i][2] 表示某个结点选还是不选能得到的某某值。可以证明这样维护是能涵盖所有情况的。

  • 状态集合清楚了,剩下还有赋值的问题,贪心地想,不是 good 的点我们都赋值最小值也就是 1,good 点周围都是非 good 点,自然赋值就是 相连的点数。

  • 此题除了要维护最大 good 数,还要维护最小权重和。所以我们的 dp 数组开成 pair 类型,优先维护 good,good 相同时维护 权重 即可。

  • 最后只需要根据 dp 性质反推方案。

Code:Code:Code:

#include<bits/stdc++.h>
#include<unordered_map>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define sca scanf
#define pri printf
#define forr(a,b,c) for(int a=b;a<=c;a++)
#define rfor(a,b,c) for(int a=b;a>=c;a--)
#define all(a) a.begin(),a.end()
#define oper(a) (operator<(const a& ee)const)
#define endl "\n"
using namespace std;typedef long long ll;
typedef pair<int, int> PII;double DNF = 1e17;
const int N = 200010, M = 400010, MM = 110;
int INF = 0x3f3f3f3f, mod = 1e9 + 7;
ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, T, S, D, K;
vector<int> e[N];
PII dp[N][2];
//dp[i][1]表示选择该点,dp[i][0]表示不选该点
//PII的一维维护最大良好顶点个数,二维维护最小顶点权重总和
//
//一个维护最大一个维护最小,有点不方便
//这里反转了一下,维护最小良好顶点个数,在最后的时候取负回正就行
int g[N];void dfs_pre(int x, int fa) {dp[x][0] = { 0,1 };//该点不选,贪心的想,权重为 1dp[x][1] = { -1,e[x].size() };//选了的话,个数 1,权值为相连点数(毕竟它们权重都是 1)for (int j : e[x]) {if (j == fa)continue;dfs_pre(j, x);//当前点 选 的情况只能由全部子节点 不选 转移过来dp[x][1].first += dp[j][0].first;dp[x][1].second += dp[j][0].second;//不选的情况,就可以根据情况转//优先最大化良好顶点的数量,数量相同选权值最小//这个过程因为我们之前反转了一维定义,所以可以直接用 PII 取 min//PII 取 min 的过程就是优先处理一维,相同再更新二维PII tmp = min(dp[j][0], dp[j][1]);dp[x][0].first += tmp.first;dp[x][0].second += tmp.second;}
}void dfs_find(int x, int fa, int c) { //c表示该点选还是不选if (c == 1)g[x] = e[x].size();else g[x] = 1;for (int j : e[x]) {if (j == fa)continue;if (c == 1)dfs_find(j, x, 0);//选只能由不选转移过来else {//否则找个小的转移if (dp[j][1] < dp[j][0])dfs_find(j, x, 1);else dfs_find(j, x, 0);}}
}void solve() {cin >> n;forr(i, 1, n - 1) {int a, b;cin >> a >> b;e[a].push_back(b);e[b].push_back(a);}if (n == 2) { //当且仅当两个顶点一条边的时候,很特殊,两点都是良好点cout << "2 2\n1 1";return;}//否则树中良好点必定不相邻,也就变成了最大独立集问题//可用选和不选的思路去树形dp,可以证明这样包含了所有情况dfs_pre(1, -1);//判断下选哪个更优,然后递归输出方案即可if (dp[1][1] < dp[1][0]) {cout << -dp[1][1].first << ' ' << dp[1][1].second << endl;dfs_find(1, -1, 1);forr(i, 1, n)cout << g[i] << ' ';}else {cout << -dp[1][0].first << ' ' << dp[1][0].second << endl;dfs_find(1, -1, 0);forr(i, 1, n)cout << g[i] << ' ';}
}int main() {cinios;T = 1;while (T--)solve();return 0;
}
/*
*/

DP顶真,鉴定为:好题

【CF1646D】D. Weight the Tree(树形dp、贪心)相关推荐

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

    Problem - 1528A - Codeforces 两个玩家正在玩一个游戏.他们有一个整数1,2,...,n的排列组合(排列组合是一个数组,其中从1到n的每个元素正好出现一次).这个排列组合没有 ...

  2. CF 1646D Weight the Tree 树形dp

    题目链接 这道题拖了很长时间才去补,今天想起来做这道题 这道题的题意是可以组成合法的点互不相邻,我的思路没有错误,但是赛时没有写出代码,现在想想也觉得可惜,我要是多想到一个度的条件,赛时可能就会过了o ...

  3. NYOJ 679 The Weight of Tree 搜索+dp+邻接表

    The Weight of Tree 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 456 has a tree of n nodes, each node is as ...

  4. 2021牛客多校4 - Rebuild Tree(树形dp)

    题目链接:点击查看 题目大意:给出一棵 nnn 个节点的树,现在可以删掉 kkk 条边,然后加上 kkk 条边,问有多少种方案使得操作后 nnn 个点仍然是一棵树 题目分析:原树删掉 kkk 条边后会 ...

  5. CodeForces - 1453E Dog Snacks(树形dp+贪心)

    题目链接:点击查看 题目大意:给出一棵有根树,现在需要选择一个最小的 k 值,可以满足下列的 n 次操作: 起始时位于点 1(根节点) 每一步选择一个未被遍历的节点中,距离最近的,且必须满足此距离小于 ...

  6. 2020CCPC(秦皇岛) - Kingdom‘s Power(树形dp+贪心)

    题目大意:给出一棵 n 个节点的有根树,点 1 为根节点,现在在根节点有无穷多个士兵,每一秒可以控制任意一个士兵向任意一个单位移动一步,士兵移动到的点会被永久占领,现在问最少需要经过多少秒,才能将所有 ...

  7. hdu-5834 Magic boy Bi Luo with his excited tree(树形dp)

    题目链接: Magic boy Bi Luo with his excited tree Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: ...

  8. HDU 5834 Magic boy Bi Luo with his excited tree 树形DP

    Magic boy Bi Luo with his excited tree 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5834 Descript ...

  9. The Lost House POJ - 2057(树形dp+贪心 (双线最优子结构问题))

    思路 题意:有一只蜗牛爬上树睡着之后从树上掉下来,发现后面的"房子"却丢在了树上面, 现在这 只蜗牛要求寻找它的房子,它又得从树根开始爬起,现在要求一条路径使得其找到房子 所要爬行 ...

  10. [Codeforces 814D] An overnight dance in discotheque 树形dp,贪心

    题目链接 题解:这道题,首先可以发现,圆与圆关系只有内含与外离, 所以可以建立出一个树形结构, 每个圆的父亲是与这个圆半径相差最小且包含这个圆的圆, 这样,整个一张图形成了一个森林,可以将圆按半径排序 ...

最新文章

  1. SOTA排行榜大变天!MIT研究十个CV测试集,平均错误率超3.4%
  2. 图像编程魔法门(By C#) 目录
  3. mysql数据库约束无符号_mysql 数据类型 约束条件
  4. OpenGL Subdivision Modes细分模式的实例
  5. java自建ocr完整示例_Java 7:完整的invokedynamic示例
  6. Solr router 路由介绍
  7. 2015第16周四自控力
  8. java 类型通配符_java中泛型之类型通配符(?)
  9. 和方舟rust一样的手游_2020年最令人期待的端改手游盘点,《方舟:生存进化》名列前茅...
  10. 从源码分析非线程安全集合类的不安全迭代器
  11. javascript基础知识练习题
  12. 智慧城市顶层设计实施工作指南
  13. Flutter AspectRatio 宽高比设定
  14. delphi去掉字段前后的引号_delphi 单引号在字符串中使用方法
  15. detached entity passed to persist问题与解决方案
  16. nestjs中生成uuid
  17. 操作系统——段式存储管理
  18. 浅析B2C电商系统开发特点
  19. Arduino 解读系列(1)数字接口/模拟接口
  20. EEG情感分析综述(三)

热门文章

  1. Unity开发win10软件系列问题6: unity调用 win10 虚拟键盘tabtip.exe
  2. 输入等值线参数绘制等值线图python_ArcGIS绘图—空气质量站点数据插值绘制等值线图...
  3. 20道经典Redis面试题
  4. vue父子组件生命周期执行顺序
  5. 商品清单计算总和(购物车)
  6. linux安装firefox
  7. java的rest教程,REST接口
  8. 数学之美:数学究竟是如何深入我们的生活
  9. Schema_CN28_CNNG净薪酬计算
  10. 【演讲实录+视频】走近40+世界级AI专家!第三届中国人工智能大会资料分享(直播进行中_不断更新)