Codeforces Round #322 (Div. 2)F 树形背包

F. Zublicanes and Mumocrates
time limit per test3 seconds
memory limit per test512 megabytes
inputstandard input
outputstandard output
It’s election time in Berland. The favorites are of course parties of zublicanes and mumocrates. The election campaigns of both parties include numerous demonstrations on n main squares of the capital of Berland. Each of the n squares certainly can have demonstrations of only one party, otherwise it could lead to riots. On the other hand, both parties have applied to host a huge number of demonstrations, so that on all squares demonstrations must be held. Now the capital management will distribute the area between the two parties.

Some pairs of squares are connected by (n - 1) bidirectional roads such that between any pair of squares there is a unique way to get from one square to another. Some squares are on the outskirts of the capital meaning that they are connected by a road with only one other square, such squares are called dead end squares.

The mayor of the capital instructed to distribute all the squares between the parties so that the dead end squares had the same number of demonstrations of the first and the second party. It is guaranteed that the number of dead end squares of the city is even.

To prevent possible conflicts between the zublicanes and the mumocrates it was decided to minimize the number of roads connecting the squares with the distinct parties. You, as a developer of the department of distributing squares, should determine this smallest number.

Input
The first line of the input contains a single integer n (2 ≤ n ≤ 5000) — the number of squares in the capital of Berland.

Next n - 1 lines contain the pairs of integers x, y (1 ≤ x, y ≤ n, x ≠ y) — the numbers of the squares connected by the road. All squares are numbered with integers from 1 to n. It is guaranteed that the number of dead end squares of the city is even.

Output
Print a single number — the minimum number of roads connecting the squares with demonstrations of different parties.

Examples
input
8
1 4
2 4
3 4
6 5
7 5
8 5
4 5
output
1
input
5
1 2
1 3
1 4
1 5
output
2

这个题其实就是最普通的树形背包
之前可能一直没有理解树形背包真正的意思
于是这个题就卡在了如何将多个子树的属性转移的上面
其实被曝部分就是个01背包
每个节点下面的子树的1点都可以看做是重量
值就是价值
这样看就很好理解了

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<memory.h>
using namespace std;
vector<int>tu[5001];
int dp[5001][5001][2];
int inf = 0x3f3f3f3f;
int dfs(int xz, int die)
{
    dp[xz][0][0] = dp[xz][0][1] = 0;
    int yigong = 0, biaoji = 1;
    for (int a = 0;a < tu[xz].size();a++)
    {
        if (tu[xz][a] == die)continue;
        biaoji = 0;
        int xzdian = dfs(tu[xz][a], xz);
        yigong += xzdian;
        for (int b = yigong;b >= 0;b--)
        {
            int da1 = inf, da0 = inf;
            for (int c = 0;c <= xzdian;c++)
            {
                da0 = min(da0, min(dp[xz][b - c][0] + dp[tu[xz][a]][c][0], dp[xz][b - c][0] + 1 + dp[tu[xz][a]][c][1]));
                da1= min(da1, min(dp[xz][b - c][1] + dp[tu[xz][a]][c][1], dp[xz][b - c][1] + 1 + dp[tu[xz][a]][c][0]));
            }
            dp[xz][b][0] = da0;
            dp[xz][b][1] = da1;
        }
    }
    if (biaoji)
    {
        dp[xz][1][1] = 0;
        dp[xz][0][1] = inf;
    }
    return yigong + biaoji;
}
int main()
{
    int n;
    cin >> n;
    if (n == 2)
    {
        cout << 1;
        return 0;
    }
    memset(dp, 0x3f, sizeof(dp));
    for (int a = 1;a <= n-1;a++)
    {
        int q, w;
        cin >> q >> w;
        tu[q].push_back(w);
        tu[w].push_back(q);
    }
    int jc = 0;
    int y = 0;
    int yu = 0;
    for (int a = 1;a <= n;a++)
    {
        if (tu[a].size() > 1)
        {
            if (!jc)dfs(a, 0),y=a,jc++;
        }
        else yu++;
    }
    cout << min(dp[y][yu / 2][0], dp[y][yu / 2][1]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值