树形dp ---- gym101655 D - Delta Quadrant 树上连通块思维换根 + 树形dp

news/2024/7/1 3:02:21

题目链接


题目大意:

给你一颗NNN个节点的树,树上每条边有边权就是遍历的时间,你可以从任意节点出发遍历N−kN-kNk个点并且回到出发点,问你最短的时间是多少?
k∈[0,min(N,20)],N∈[1,1e4]k\in[0,min(N,20)],N\in[1,1e4]k[0,min(N,20)],N[1,1e4]


解题思路:

思维误区:一开始我对于这个任意节点出发以为是要换根,但是子父之间的关系不好找!!,而且我定义的状态方程是dp[i][j]dp[i][j]dp[i][j]iii这个子树里不选jjj个点的花费的最小时间。这个无法更新:因为它一定要联通,我这个方程只表明了不选jjj个点无法保证联通性!!!

其实这个任意点出发是没关系的:假设我们固定一个111号点为根,那么答案肯定是一个连通块,那么连通块里面你从任意一个点出发都可以得到同一个答案,那么我们可以就假设从这个联通块里面深度最小的那个节点出发得到的结果!!
在这里插入图片描述

那么为了得到连通块:我们dp[i][j]dp[i][j]dp[i][j]要加上一个限制:就是iii这个子树里面不选jjj个点,并且iii这个点一定要选!! 再加上前面的限制就是并且iii号点一定是连通块里面深度最低的点!!

那么我们dpdpdp就很好转移了:如果有多个子树我们分别枚举在两个子树里面分别不选多少就好了!!

更新答案的时候我们要用全局ansansans去更新:
假设我们现在到了uuu号点,那么我们默认是uuu子树之外的点是不选的

if(n-siz[u]<=k) ans = min(ans,dp[u][k-(n-siz[u])]);

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 = 500010;
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...);
}
vector<PII> G[maxn];
int n,k;
ll dp[maxn][25], ans; // dp[i][j] 表示从 i 这子树里面一定选i这个点并且不选j个点的最小花费
int siz[maxn];
inline void dfs(int u, int fa) {bool tag = 0;siz[u] = 1;for(auto it : G[u]) {if(it.first == fa) continue;dfs(it.first,u);siz[u] += siz[it.first];if(!tag) { // 判断有多少个子树for(int i = 0; i <= min(k,siz[it.first]); ++ i) dp[u][i] = dp[it.first][i] + it.second;if(siz[it.first] <= k) dp[u][siz[it.first]] = 0; tag = 1;} else {ll res[25];for(int i = 0; i <= k; ++ i) res[i] = LLF;for(int j = 0; j <= k; ++ j) // 枚举分别不拿多少个?for(int i = 0; i <= j; ++ i) {if(siz[it.first] <= j - i)res[j] = min(res[j],dp[u][i]);else res[j] = min(res[j],dp[u][i]+dp[it.first][j-i]+it.second); }for(int i = 0; i <= k; ++ i) dp[u][i] = res[i];}}if(n-siz[u]<=k) ans = min(ans,dp[u][k-(n-siz[u])]);if(G[u].size() == 1 && u != 1) dp[u][0] = 0; // 叶子节点更新答案 只有这个是合法的
}int main() {IOS;int _;cin >> _;while(_--) {ans = LLF;cin >> n >> k;for(int i = 0; i <= n+1; ++ i) G[i].clear();for(int i = 1; i < n; ++ i) {int u, v, w;cin >> u >> v >> w;u ++, v ++; // 把编号调到[1,n]G[u].push_back({v,w});G[v].push_back({u,w});}for(int i = 0; i <= n; ++ i)for(int j = 0; j <= 20; ++ j)dp[i][j] = LLF;dfs(1,0);cout << ans * 2ll << "\n";} 
}
/*
3
2 0
0 1 3000
4 1
0 1 81
1 2 41
2 3 59
9 2
0 1 1000
1 2 1200
0 3 1000
3 4 1200
0 5 1000
5 6 1200
0 7 1800
7 8 600
*/

http://lihuaxi.xjx100.cn/news/285940.html

相关文章

任正非:要感谢特朗普,他一吓唬,治好了华为人的富裕病,都努力工作了

华为“心声社区”前几日公布了任正非接受北欧媒体采访的纪要。据纪要显示&#xff0c;前几日任正非接受采访&#xff0c;参与采访的记者来自瑞典国家电视台、丹麦广播公司等多家媒体。任正非在采访中就华为建筑的欧式设计、美国总统特朗普、5G和人工智能等问题作答。任正非(图源…

寒假要完成的任务

这个寒假&#xff0c;我要做的很多&#xff0c;一下是我做了一小的总结&#xff0c;便于提醒自己。 我要做的有这个几个&#xff1a;1.蓝桥杯&#xff0c;每天2道题2.学习Heberate ,spring &#xff0c;三大框架3.做项目&#xff0c;学习android4.去完成计算机网络三、四级&…

《中国人工智能ABC人才发展报告》发布,算法和应用类人才短缺

近日&#xff0c;百度云联手中国传媒大学、BOSS 直聘和百度指数发布了《中国人工智能 ABC 人才发展报告&#xff08;2018版&#xff09;》&#xff08;以下简称“报告”&#xff09;和百度云智学院2019 年人才认证体系。报告指出&#xff0c;从 2018 年的人才供需状况来看&…

Codeforces Round #640 (Div. 4)(ABCDEG题解)

文章目录A. Sum of Round NumbersB - Same Parity SummandsC - K-th Not Divisible by nD - Alice, Bob and CandiesE - Special ElementsF. Binary String ReconstructionG - Special PermutationA. Sum of Round Numbers 题解&#xff1a;把他一个整数拆分&#xff0c;模拟一…

第1关:实现一个顺序存储的线性表

#if !defined(Seqlist__CIELSI_989SE_AJIEZN_728JULC__INCLUDED_) #define Seqlist__CIELSI_989SE_AJIEZN_728JULC__INCLUDED_ typedef int T; // 数据元素的数据类型 struct SeqList{T* data; // 数据元素的开始地址int len; // 当前长度int max; // 线性表的最大长度 };SeqL…

一文带你看懂Springboot核心功能及优缺点

点击上方[视学算法]→右上角[...]→[设为星标⭐]SpringBoot核心功能1、独立运行Spring项目Spring boot 可以以jar包形式独立运行&#xff0c;运行一个Spring Boot项目只需要通过java -jar xx.jar来运行。2、内嵌servlet容器Spring Boot可以选择内嵌Tomcat、jetty或者Undertow,这…

最小费用最大流 ---- 2017icpc青岛现场赛 K Our Journey of Xian Ends (拆点控制原图点度 + 中间必经过的点设置成源点 + 起点设成汇点)

题目链接 题目大意&#xff1a; 题目贼恶心难读 就是你出发地是"Xian"西安&#xff0c;现在你要出发到上海然后再去青岛&#xff0c;然后回到上海 飞机场限制&#xff1a;就是每个机场只能降落和起飞一次 上海的限制&#xff1a;上海有两个机场&#xff0c;叫虹桥…

koa-grace:一个基于koa的node多应用MVC框架

春节期间没回家留在北京写了一个基于koa的node MVC框架&#xff1a;koa-grace &#xff0c;大家有兴趣可以star & fork下&#xff0c;谢谢支持啦&#xff01;&#xff01; 项目地址&#xff1a; https://github.com/xiongwilee/koa-grace 详细文档&#xff1a; 1. 简介 koa…