NeFut Logo NeFut
Admin Login

High-Dimensional Mapping Techniques in Tree Dynamic Programming

Published at: 2026-05-27 09:17 Last updated: 2026-06-06 13:04
#algorithm #Tree #DP

Core Logic and Mathematical Principles

The basic model of Tree Dynamic Programming (Tree DP) usually focuses only on the convergence of states within subtrees (e.g., bottom-up). However, high-difficulty problems in contests often introduce full-source topological interactions or local connectivity block constraints.

To overcome the highest threshold of Tree DP, one must thoroughly master the following two core high-dimensional mapping techniques:

  1. Multi-state Interleaving: When the problem constraints are no longer simply "select or not select" (e.g., at a ball without a supervisor), but rather involve multi-level transmission chains (for example: a node is covered by security, which can be because it has surveillance installed, or its parent does, or one of its children does). This multi-directional dependency can cause traditional two-dimensional states to collapse completely. We must establish a fully complete state set and create cross-dimensional grid interleaving between parent and child nodes.
  2. Re-rooting Context Isolation: In Section 16.3's re-rooting method, we encountered the transfer of full-source information. However, in more complex scenarios (such as finding the second largest value of Hamming distance on a tree or when the transfer equation includes non-invertible operators), the simple differential logic of "global - subtree = external" fails. At this point, it is necessary to maintain prefix and suffix value grids for all direct child nodes of the parent during the first scan, so that when re-rooting downwards, we can extract the aggregate contributions of "all other sibling subtrees except the current child subtree" without loss.

State Design and Algorithm Derivation

Taking the classic "Minimum Dominating Set of Trees" as an example (i.e., selecting the minimum number of nodes to color black so that all nodes in the tree are either colored black themselves or adjacent to at least one black node).

1. Fully Complete State Space Design

For any node $u$, to ensure that the subtree rooted at $u$ is fully covered legally and meets topological transmission, its own state can have only the following 3 completely complete physical semantics:

2. Geometric Interleaving of State Transition Equations

For the parent node $u$ and its child node set $ ext{son}(u)$:

$$f[u][0] = 1 + \sum_{v \in \text{son}(u)} \min(f[v][0], f[v][1], f[v][2])$$

$$f[u][2] = \sum_{v \in \text{son}(u)} \min(f[v][0], f[v][1])$$

$$f[u][1] = \sum_{v \in \text{son}(u)} \min(f[v][0], f[v][1]) + \Delta_{min}$$

Where $\Delta_{min} = \min_{v \in \text{son}(u)} \{ f[v][0] - \min(f[v][0], f[v][1]) \}$. If there is already a child selected state 0 in the original combination, then $\Delta_{min} = 0$.


C++ Standard Source Code (NOIP Style)

The following code is a standard industrial implementation of the Minimum Dominating Set of Trees, perfectly demonstrating the fine control of multi-state network interaction in contests.

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int MAXN = 100005;
const int INF = 0x3f3f3f3f;

vector<int> edge[MAXN];
int f[MAXN][3]; 
// f[u][0]: u black
// f[u][1]: u white, covered by children black
// f[u][2]: u white, covered by parent black

void dfs(int u, int fa) {
    f[u][0] = 1; // Initial cost for being colored black is 1
    f[u][2] = 0; // Current local initialization cost for waiting for parent to cover is 0

    int sum_1_0 = 0;
    int min_gap = INF;
    bool has_zero = false; // Record whether any child has spontaneously chosen state 0

    // Sentinel flag to check if it is a leaf node
    bool is_leaf = true;

    for (int v : edge[u]) {
        if (v == fa) continue;
        is_leaf = false;

        dfs(v, u); // Topological sinking

        // 1. Update f[u][0]
        f[u][0] += min({f[v][0], f[v][1], f[v][2]});

        // 2. Update f[u][2]
        f[u][2] += min(f[v][0], f[v][1]);

        // 3. Collect baseline sum for f[u][1] and calculate the gap
        int best_sub = min(f[v][0], f[v][1]);
        sum_1_0 += best_sub;

        if (f[v][0] <= f[v][1]) {
            has_zero = true;
        }
        min_gap = min(min_gap, f[v][0] - best_sub);
    }

    // Edge case for leaf nodes: assign physical extreme values
    if (is_leaf) {
        f[u][0] = 1;
        f[u][1] = INF; // Leaf has no children, cannot rely on children to cover, assign infinity
        f[u][2] = 0;   // Waiting for parent to cover is legitimate
        return;
    }

    // 4. Fine-tune the combination of f[u][1] state
    if (has_zero) {
        f[u][1] = sum_1_0; // Already has a child selected 0, no need to force a compensatory cost
    } else {
        f[u][1] = sum_1_0 + min_gap; // Forcibly pull the child with the smallest cost increase to state 0
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    if (!(cin >> n)) return 0;

    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        edge[u].push_back(v);
        edge[v].push_back(u);
    }

    dfs(1, 0);

    // The root node has no parent, so the global optimal solution can only be found in state 0 and state 1
    cout << min(f[1][0], f[1][1]) << "\n";

    return 0;
}

NOIP Practical Pitfall Guide

1. Ignoring Special Boundary State Assignments for Leaf Nodes

2. Unhandled INF in Gap Calculation Leading to Data Overflow


Classic NOIP/Luogu Problems

1. Luogu P2899 [USACO08JAN] Cell Phone Network G

2. Luogu P2458 [SDOI2006] Security Station Assignment

$$f[u][0] = W[u] + \sum \min(f[v][0], f[v][1], f[v][2])$$

The decision flow for relying on children and relying on parents remains identical, and the gap logic is completely consistent. This problem maps discrete counting losslessly to a continuous cost grid, making it a classic high-frequency problem for selection and NOIP advanced groups.

Original Source: local://16.4

[h] Back to Home