luoguP2015 二叉苹果树
给定一棵N个节点的苹果树,根节点编号为1。如果树枝有分叉,一定是分二叉。已知节点a与b的边权为w[a][b]。求一棵树,最多有Q条边,并且边权之和最大。
1<=Q<N<=100; 0<=w[i][j]<=3E4
分析:Q条边的树对应Q+1个节点,转化为节点数限制,可以用树上背包的方法来做。记dp[x][j]表示以x为根,选择节点数不超过j的最大权值之和,对于节点x,如果要选其子节点i,那么必须选上x,可以枚举子节点的节点数进行递推。
#include <bits/stdc++.h> using i64 = long long; void solve() { int N, Q; std::cin >> N >> Q; std::vector<std::vector<int>> adj(N); std::vector<std::vector<int>> w(N, std::vector<int>(N)); for (int i = 1; i < N; i++) { int x, y, z; std::cin >> x >> y >> z; x--, y--; w[x][y] = w[y][x] = z; adj[x].push_back(y); adj[y].push_back(x); } std::vector<std::vector<int>> dp(N, std::vector<int>(Q + 2)); auto dfs = [&](auto self, int x, int p) -> void { for (int i = 1; i <= Q + 1; i++) { dp[x][i] = w[x][p]; } for (auto i : adj[x]) if (i != p) { self(self, i, x); for (int j = Q + 1; j >= 1; j--) { for (int k = 0; k < j; k++) { dp[x][j] = std::max(dp[x][j], dp[i][k] + dp[x][j - k]); } } } }; dfs(dfs, 0, 0); std::cout << dp[0][Q + 1] << "\n"; } int main() { std::cin.tie(0)->sync_with_stdio(0); int t = 1; while (t--) solve(); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】