C++树形DP(选与不选模型)
·
树形DP 代码框架见下
#include <iostream>
#include <vector>
using namespace std;
#define type int
#define maxn 200010
#define inf 1000000000
int n;
// dp[i][0]代表以i为根节点的子树,且根节点不选最大(小)值(或者方案数)
// dp[i][1]代表以i为根节点的子树,且根节点 选最大(小)值(或者方案数)
type dp[maxn][2];
vector<int> child[maxn];
type TreeDPSample_InitVal(int u, int isChoose) {
return isChoose;
}
type TreeDPSample_Opt(type curVal, bool isChoose, type ncVal, type cVal) {
if (isChoose) {
return curVal + min(ncVal, cVal);
}
return curVal + cVal;
}
void TreeDPSample_Init(int n) {
for (int i = 0; i <= n; ++i) {
dp[i][0] = dp[i][1] = inf;
}
}
type TreeDPSample_DFS(int u, bool isChoose, int fat) {
type& ans = dp[u][isChoose];
if (ans != inf) {
return ans;
}
ans = TreeDPSample_InitVal(u, isChoose);
for (int i = 0; i < child[u].size(); ++i) {
int v = child[u][i];
if (v == fat) {
continue;
}
type nc = TreeDPSample_DFS(v, false, u);
type c = TreeDPSample_DFS(v, true, u);
ans = TreeDPSample_Opt(ans, isChoose, nc, c);
}
return ans;
}
int main()
{
cin >> n;
TreeDPSample_Init(n);
for (int i = 0; i < n - 1; ++i) {
int x, y;
cin >> x >> y;
child[x].push_back(y);
child[y].push_back(x);
}
type ans = min(
TreeDPSample_DFS(1, true, 0),
TreeDPSample_DFS(1, false, 0)
);
cout << ans << endl;
// 请在此输入您的代码
return 0;
}
代码练习 1 对应蓝桥云课 生命之树
#include <iostream>
#include <vector>
using namespace std;
#define type long long
#define maxn 100010
#define inf -1000000000000000011
int n;
// dp[i][0]代表以i为根节点的子树,且根节点不选最大(小)值(或者方案数)
// dp[i][1]代表以i为根节点的子树,且根节点 选最大(小)值(或者方案数)
type dp[maxn][2];
vector<int> child[maxn];
type a[maxn];
type TreeDPSample_InitVal(int u, int isChoose) {
return a[u] * isChoose;
}
type TreeDPSample_Opt(type curVal, bool isChoose, type ncVal, type cVal) {
if (isChoose) {
return curVal + max(ncVal, cVal);
}
return 0;
}
void TreeDPSample_Init(int n) {
for (int i = 0; i <= n; ++i) {
dp[i][0] = dp[i][1] = inf;
}
}
type TreeDPSample_DFS(int u, bool isChoose, int fat) {
type& ans = dp[u][isChoose];
if (ans != inf) {
return ans;
}
ans = TreeDPSample_InitVal(u, isChoose);
for (int i = 0; i < child[u].size(); ++i) {
int v = child[u][i];
if (v == fat) {
continue;
}
type nc = TreeDPSample_DFS(v, false, u);
type c = TreeDPSample_DFS(v, true, u);
ans = TreeDPSample_Opt(ans, isChoose, nc, c);
}
return ans;
}
int main()
{
cin >> n;
TreeDPSample_Init(n);
for(int i=1; i <= n; ++i){
cin >> a[i];
}
for (int i = 0; i < n - 1; ++i) {
int x, y;
cin >> x >> y;
child[x].push_back(y);
child[y].push_back(x);
}
type ans = inf;
for(int i=1; i <= n; ++i){
TreeDPSample_DFS(i, 0, 0);
TreeDPSample_DFS(i, 1, 0);
ans = max(ans, max(dp[i][0], dp[i][1]));
}
cout << ans << endl;
// 请在此输入您的代码
return 0;
}
代码练习 2 树的着色问题 对应蓝桥云课 代码见下
#include <iostream>
#include <vector>
using namespace std;
#define mod 1000000007
#define type long long
#define maxn 100010
#define inf 1000000000
int n;
// dp[i][0]代表以i为根节点的子树,且根节点不选最大(小)值(或者方案数)
// dp[i][1]代表以i为根节点的子树,且根节点 选最大(小)值(或者方案数)
type dp[maxn][2];
vector<int> child[maxn];
int a[maxn];
type TreeDPSample_InitVal(int u, int isChoose) {
return 1;
}
type TreeDPSample_Opt(type curVal, bool isChoose, type ncVal, type cVal) {
if (isChoose) {
return curVal * ncVal % mod;
}
return curVal * (ncVal + cVal) % mod;
}
void TreeDPSample_Init(int n) {
for (int i = 0; i <= n; ++i) {
dp[i][0] = dp[i][1] = inf;
}
}
type TreeDPSample_DFS(int u, bool isChoose, int fat) {
type& ans = dp[u][isChoose];
if (ans != inf) {
return ans;
}
ans = TreeDPSample_InitVal(u, isChoose);
for (int i = 0; i < child[u].size(); ++i) {
int v = child[u][i];
if (v == fat) {
continue;
}
type nc = TreeDPSample_DFS(v, false, u);
type c = TreeDPSample_DFS(v, true, u);
ans = TreeDPSample_Opt(ans, isChoose, nc, c);
}
return ans;
}
int main()
{
cin >> n;
TreeDPSample_Init(n);
for (int i = 0; i < n - 1; ++i) {
int x, y;
cin >> x >> y;
child[x].push_back(y);
child[y].push_back(x);
}
type ans = (
TreeDPSample_DFS(1, true, 0) +
TreeDPSample_DFS(1, false, 0)
) % mod;
cout << ans << endl;
// 请在此输入您的代码
return 0;
}
代码练习 3 对应蓝桥云课 没有上司的舞会 代码见下
#include <iostream>
#include <vector>
using namespace std;
#define type int
#define maxn 5010
#define inf -1000000000
int n;
// dp[i][0]代表以i为根节点的子树,且根节点不选最大(小)值(或者方案数)
// dp[i][1]代表以i为根节点的子树,且根节点 选最大(小)值(或者方案数)
type dp[maxn][2];
vector<int> child[maxn];
int a[maxn];
type TreeDPSample_InitVal(int u, int isChoose) {
return a[u] * isChoose;
}
type TreeDPSample_Opt(type curVal, bool isChoose, type ncVal, type cVal) {
if (isChoose) {
return curVal + ncVal;
}
return curVal + max(ncVal, cVal);
}
void TreeDPSample_Init(int n) {
for (int i = 0; i <= n; ++i) {
dp[i][0] = dp[i][1] = inf;
}
}
type TreeDPSample_DFS(int u, bool isChoose, int fat) {
type& ans = dp[u][isChoose];
if (ans != inf) {
return ans;
}
ans = TreeDPSample_InitVal(u, isChoose);
for (int i = 0; i < child[u].size(); ++i) {
int v = child[u][i];
if (v == fat) {
continue;
}
type nc = TreeDPSample_DFS(v, false, u);
type c = TreeDPSample_DFS(v, true, u);
ans = TreeDPSample_Opt(ans, isChoose, nc, c);
}
return ans;
}
int main()
{
cin >> n;
TreeDPSample_Init(n);
for(int i=1; i <= n; ++i){
cin >> a[i];
}
for (int i = 0; i < n - 1; ++i) {
int x, y;
cin >> x >> y;
child[x].push_back(y);
child[y].push_back(x);
}
type ans = max(
TreeDPSample_DFS(1, true, 0),
TreeDPSample_DFS(1, false, 0)
);
cout << ans << endl;
// 请在此输入您的代码
return 0;
}
更多推荐


所有评论(0)