[SMOJ1784]拜访奶牛

97 篇文章 0 订阅
11 篇文章 0 订阅

题目描述

输入格式 1784.in

输出格式 1784.out

输入样例 1784.in

输出样例 1784.out


我们来分析一下样例:

三个叶子结点的情况是显然的,选就能选 1 个,不选就能选 0 个。我们还是忽略不看,从它们的父亲结点开始考虑。

在以 6 为根的子树里面,如果不选 6 可以选 5 和 7 这 2 个,选 6 则只能选 1 个。

在以 2 为根的子树里面,选 2(2、5 和 7)或不选(1、5 和 7)都能选 3 个。

在以 3 为根的子树里面,选 3 (3、1、5 和 7)可以选 4 个,不选([1 或 2]、5 和 7)可以选 3 个。

整个问题的答案,以 4 为根的子树里面,选 4(4、[1 或 2]、5 和 7)可以选 4 个,不选(3、1、5 和 7)也可以选 4 个。

回想一下,求解的过程中,我们在分类讨论考虑的时候,影响决策的就是:如果选了这个根,那么它的儿子都不能选,于是选这个根的答案就是它的所有儿子不选的总和。如果不选这个根,它的儿子选不选都没问题,那么不选这个根的答案就是它的每个儿子选和不选中最大值的总和。

好了,现在我们知道,这其实就是一个1782 最大利润的简化版本,只不过所有点的权值为 1,其他几乎是一模一样的。

参考代码:

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

const int maxn = 5e4 + 100;

int n;

vector <int> g[maxn];
int dp[maxn][5];

bool vis[maxn];

void dfs(int r) {
    vis[r] = true;
    dp[r][1] = 1;
    dp[r][0] = 0;
    for (int i = 0; i < g[r].size(); i++)
        if (!vis[g[r][i]]) {
            dfs(g[r][i]);
            dp[r][0] += max(dp[g[r][i]][0], dp[g[r][i]][1]);
            dp[r][1] += dp[g[r][i]][0];
        }
}

int main(void) {
    freopen("1784.in", "r", stdin);
    freopen("1784.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 1; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        g[x].push_back(y); g[y].push_back(x);
    }
    memset(vis, false, sizeof vis);
    dfs(1);
    printf("%d\n", max(dp[1][0], dp[1][1]));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值