LibreOJ 10156 战略游戏

题目链接:LibreOJ 10156 战略游戏

题目大意:

题解:
很明显是树形\(dp\)题。
\(dp[i][0/1]\)表示第\(i\)个点不放/放士兵所需的最少士兵数。
如果当前节点不放士兵,子节点要放士兵;如果当前节点放士兵,子节点可放可不放。
状态转移方程为:

\[\left\{\begin{aligned} dp[u][0] &= \sum dp[v][1] \\ dp[u][1] &= 1+\sum min\{dp[v][0], dp[v][1]\} \end{aligned}\right. \]

#include <cstring>
#include <iostream>
using namespace std;
#define N 1510

int n, head[N], cnt, dp[N][2];
struct Edge {
    int v, next;
} edge[N << 1];

void addEdge(int u, int v) {
    edge[++cnt].v = v;
    edge[cnt].next = head[u];
    head[u] = cnt;
}

void dfs(int u, int pre) {
    dp[u][0] = 0;
    dp[u][1] = 1;
    for (int i = head[u]; ~i; i = edge[i].next) {
        int v = edge[i].v;
        if (v == pre) {
            continue;
        }
        dfs(v, u);
        dp[u][0] += dp[v][1];
        dp[u][1] += min(dp[v][0], dp[v][1]);
    }
}

int main() {
    memset(head, -1, sizeof(head));
    cin >> n;
    for (int i = 1, u, k; i <= n; ++i) {
        cin >> u >> k;
        for (int j = 1, v; j <= k; ++j) {
            cin >> v;
            addEdge(u, v);
            addEdge(v, u);
        }
    }
    dfs(0, -1);
    cout << min(dp[0][1], dp[0][0]);
    return 0;
}
posted @ 2021-07-28 00:31  ZZHHOOUU  阅读(35)  评论(0编辑  收藏  举报