树形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;
}

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐