Codeforces 581F Zublicanes and Mumocrates - 树形动态规划
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.
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.
Print a single number — the minimum number of roads connecting the squares with demonstrations of different parties.
8
1 4
2 4
3 4
6 5
7 5
8 5
4 5
1
5
1 2
1 3
1 4
1 5
2
题目大意
给定一棵有$n$个点的无根树(度为1的点不为根),保证它的叶节点的个数为偶数。将所有点染成黑白两种颜色,要求
- 黑的叶节点数等于白的叶节点数
- 有边相连但颜色不同的点对数最少
问最少的这样的点对数。
显然动态规划。
Solution 1
用$f[i][j][0/1]$表示当前考虑$i$号点,它的子树内有$j$个叶节点是黑色的最优结果。
转移是显然的。
至于时间复杂度为什么可过?下面解释一下(为了方便计算,那么就用子树$size$来说明吧)
设当前考虑的节点的第$i$个子节点为$s_{i}$。
$\sum_{i = 1}size[s_{i}]\cdot\sum_{j = 1} ^ {i - 1}size[s_{j}] = \sum_{i < j}size[s_{i}]\cdot size[s_{j}]$
然后可以发现对于任意一对节点$\left(u, v\right)$仅对它们的lca有1的贡献,所以总时间复杂度为$O\left(n^{2}\right)$
Code
/**
* Codeforces
* Problem#581F
* Accepted
* Time: 139ms
* Memory: 198380k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;
#define smin(_a, _b) (_a = min(_a, _b)) const int N = ; int n;
vector<int> *g;
// 0: black, 1: white
int f[N][N][]; // node, number of the black nodes, the color of this node
int temp[N][];
int root;
int clf[N];
int deg[N]; inline void init() {
scanf("%d", &n);
g = new vector<int>[(n + )];
for(int i = , u, v; i < n; i++) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
deg[u]++, deg[v]++;
}
for(root = ; root < n && deg[root] == ; root++);
} void treedp(int node, int fa) {
if(deg[node] == ) {
f[node][][] = f[node][][] = ;
clf[node] = ;
return;
}
// memset(temp)
clf[node] = ;
f[node][][] = f[node][][] = ;
for (int i = ; i < deg[node]; i++) {
int e = g[node][i];
if (e == fa) continue;
treedp(e, node);
memset(temp, 0x3f, sizeof(temp));
for (int s1 = clf[node]; ~s1; s1--) {
for (int s2 = clf[e]; ~s2; s2--) {
smin(temp[s1 + s2][], f[node][s1][] + min(f[e][s2][], f[e][s2][] + ));
smin(temp[s1 + s2][], f[node][s1][] + min(f[e][s2][] + , f[e][s2][]));
}
}
clf[node] += clf[e];
for (int j = ; j <= clf[node]; j++)
f[node][j][] = temp[j][], f[node][j][] = temp[j][];
}
} inline void solve() {
memset(f, 0x3f, sizeof(f));
treedp(root, );
int k = clf[root] >> ;
int ans = min(f[root][k][], f[root][k][]);
printf("%d\n", ans);
} int main() {
init();
solve();
return ;
}
Slower Version
Solution 2
由于转移的时候仅和当前节点的颜色和它的父节点的颜色是否相同有关,所以用$f[i][j]$表示当前考虑第$i$号点,它的子树内有$j$个叶节点是黑色的最优结果。
怎么转移呢?
先当父节点颜色和当前节点颜色相同,按照上面的方法进行转移。
然后考虑将当前子树内的所有点的颜色反转,这样会导致当前点和父节点的颜色不同,答案加1,这样去更新。
Code
/**
* Codeforces
* Problem#581F
* Accepted
* Time: 61ms
* Memory: 100280k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;
#define smin(_a, _b) (_a = min(_a, _b)) const int N = ; int n;
vector<int> g[N];
int f[N][N]; // node, number of the black nodes
int root;
int clf[N];
int deg[N]; inline void init() {
scanf("%d", &n);
for(int i = , u, v; i < n; i++) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
deg[u]++, deg[v]++;
}
for(root = ; root < n && deg[root] == ; root++);
} void treedp(int node, int fa) {
if(deg[node] == ) {
f[node][] = , f[node][] = ;
clf[node] = ;
return;
}
clf[node] = ;
f[node][] = ;
for (int i = ; i < deg[node]; i++) {
int e = g[node][i];
if (e == fa) continue;
treedp(e, node);
for (int s1 = clf[node]; ~s1; s1--) {
for (int s2 = clf[e]; ~s2; s2--) {
smin(f[node][s1 + s2], f[node][s1] + f[e][s2]);
}
}
clf[node] += clf[e];
}
for (int i = ; i <= clf[node]; i++)
smin(f[node][i], f[node][clf[node] - i] + ); // reverse the color of each node
} inline void solve() {
memset(f, 0x3f, sizeof(f));
treedp(root, );
int k = clf[root] >> ;
printf("%d\n", f[root][k]);
} int main() {
init();
solve();
return ;
}
Codeforces 581F Zublicanes and Mumocrates - 树形动态规划的更多相关文章
- Codeforces 581F Zublicanes and Mumocrates 树形dp
Zublicanes and Mumocrates dp[ i ][ j ][ k ] 表示 以 i 为根的子树, 占领 i 的 是 j 并且第一个人占了 i 子树的 k 个叶子节点的最小值. 然后随 ...
- Codeforces 581F Zublicanes and Mumocrates(树形DP)
题目大概说有一棵树要给结点染色0或1,要求所有度为1的结点一半是0一半是1,然后问怎么染色,使两端点颜色不一样的边最少. dp[0/1][u][x]表示以u结点为根的子树中u结点是0/1色 且其子树有 ...
- Codeforces 581F Zublicanes and Mumocrates(树型DP)
题目链接 Round 322 Problem F 题意 给定一棵树,保证叶子结点个数为$2$(也就是度数为$1$的结点),现在要把所有的点染色(黑或白) 要求一半叶子结点的颜色为白,一半叶子结点的 ...
- 树形dp - Codeforces Round #322 (Div. 2) F Zublicanes and Mumocrates
Zublicanes and Mumocrates Problem's Link Mean: 给定一个无向图,需要把这个图分成两部分,使得两部分中边数为1的结点数量相等,最少需要去掉多少条边. ana ...
- Codeforces Round #322 (Div. 2) —— F. Zublicanes and Mumocrates
It's election time in Berland. The favorites are of course parties of zublicanes and mumocrates. The ...
- Codeforces 835F Roads in the Kingdom - 动态规划
题目传送门 传送点I 传送点II 传送点III 题目大意 给定一颗基环树,要求删去其中一条边,使得剩下的图形是一棵树,并且最长路的长度最短,求最长路的最短长度. 路径可以分为两部分:跨过环 和 在树内 ...
- 蓝桥杯 ALGO-4 结点选择 (树形动态规划)
问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值.如果一个点被选择了,那么在树上和它相邻的点都不能被选择.求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n . 接下来的 ...
- 树形动态规划(树状DP)小结
树状动态规划定义 之所以这样命名树规,是因为树形DP的这一特殊性:没有环,dfs是不会重复,而且具有明显而又严格的层数关系.利用这一特性,我们可以很清晰地根据题目写出一个在树(型结构)上的记忆化搜索的 ...
- Codeforces 1000G Two-Paths 树形动态规划 LCA
原文链接https://www.cnblogs.com/zhouzhendong/p/9246484.html 题目传送门 - Codeforces 1000G Two-Paths 题意 给定一棵有 ...
随机推荐
- 递归n!
package sushudigui; import java.util.Scanner; public class digui { public static void main(String[] ...
- python爬虫-基础入门-python爬虫突破封锁
python爬虫-基础入门-python爬虫突破封锁 >> 相关概念 >> request概念:是从客户端向服务器发出请求,包括用户提交的信息及客户端的一些信息.客户端可通过H ...
- 如何简单地理解Python中的if __name__ == '__main__'(https://blog.csdn.net/yjk13703623757/article/details/77918633)
1. 摘要 通俗的理解__name__ == '__main__':假如你叫小明.py,在朋友眼中,你是小明(__name__ == '小明'):在你自己眼中,你是你自己(__name__ == '_ ...
- mysql字符集问题,及排序规则
字符集问题: 基本概念 • 字符(Character)是指人类语言中最小的表义符号.例如’A'.’B'等:• 给定一系列字符,对每个字符赋予一个数值,用数值来代表对应的字符,这一数值就是字符的编码(E ...
- Android -- 仿淘宝广告条滚动
1,在赶项目的时候我们经常会实现下面这个功能,及添加滚动条广告广播,先看一下淘宝的效果 2,这次实现效果主要使用Android自带的ViewFlipper控件,先来看一下我们的它的基本属性和基本方法吧 ...
- github上删除一个项目或者reposity
1,点击github的头像,选择如下操作. 2.选择要删除的reposity 3.选择settings 4.复制reposity名字,然后下滑鼠标到底部,选择delete this reposity ...
- 四 js Math数学简单使用
//Math是全局的 //Math.PI 数学里的3.1415926.... console.log(Math.PI); //取随机数 //js提供的随机函数 Math.random() --> ...
- 内网渗透之如何玩转Meterpreter?(nc.exe)
十.Meterpreter常用命令 1.基本命令(包含meterpreter和msf终端.ruby接口.目标shell交互的命令) background(进程隐藏至后台) sessions(查看已经成 ...
- python 正则基本方法
2017-04-11 学习python,免不了应对爬虫,初学爬虫最难理解的就是正则表达式. 比如我们要爬去网页上的某些内容,就像下面这种形式: <p>safdsf</p>< ...
- Java注解的原理
自Java5.0版本引入注解之后,它就成为了Java平台中非常重要的一部分.开发过程中,我们也时常在应用代码中会看到诸如@Override,@Deprecated这样的注解.这篇文章中,我将向大家讲述 ...