HZNU-ACM寒假集训Day10小结 树-树形DP
树形DP
加分二叉树 洛谷P1040

注意中序遍历的特点:当根节点编号k时,编号小于k的都在其左子树上,编号大于k的都在右子树
转移方程 f[i,j]=max{f[i,k-1]*f[k+1,j]+d[k]} ,f[i,j]表示中序遍历i到j的二叉树最大加分 时间复杂度O(N3)
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<cmath>
const double PI = acos(-1.0);
typedef long long ll;
using namespace std; const int maxn = ;
int n, m;
int f[maxn][maxn], root[maxn][maxn], num[maxn]; void print(int l, int r) { //先序遍历 根->左子树->右子树
printf("%d ", root[l][r]);
if (root[l][r] > l) print(l, root[l][r] - );
if (root[l][r] < r) print(root[l][r] + , r);
} int main() {
scanf("%d", &n);
for (int i = ; i <= n; i++) {
scanf("%d", &num[i]);
f[i][i] = num[i];
root[i][i] = i;
f[i][i - ] = f[i + ][i] = ;
}
for (int i = n; i >= ; i--) {
for (int j = i + ; j <= n; j++) {
for (int k = i; k <= j; k++) {
if (f[i][k - ] * f[k + ][j] + f[k][k] <= f[i][j]) continue;
f[i][j] = f[i][k - ] * f[k + ][j] + f[k][k];
root[i][j] = k;
}
}
}
printf("%d\n", f[][n]);
print(, n);
return ;
}
P2015 二叉苹果树

#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<cmath>
const double PI = acos(-1.0);
typedef long long ll;
using namespace std; int n, cnt[], dp[][];
int q;
struct Edge {
int w;
int e;
}t;
vector<Edge> e[];
void dfs(int u, int p) {
for (int i = ; i < e[u].size(); i++) {
int v = e[u][i].e;
if (v == p) continue;
dfs(v, u);
cnt[u] += cnt[v] + ;
for (int j = min(cnt[u], q); j; j--) {
for (int k = min(j - , cnt[v]); k >= ;)
dp[u][j] = max(dp[u][j], dp[u][j - k - ] + dp[v][k] + e[u][i].w);
}
}
}
int main() {
scanf("%d%d", &n, &q);
for (int i = ; i < n; i++) {
int x, y, w;
scanf("%d%d%d", &x, &y, &w);
t.e = y;
t.w = w;
e[x].push_back(t);
t.e = x;
e[y].push_back(t);
}
dfs(, );
printf("%d", dp[][q]);
return ;
}
洛谷P1352 没有上司的舞会
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<cmath>
const double PI = acos(-1.0);
typedef long long ll;
using namespace std; const int maxn = ;
int w[maxn];
int v[maxn];
int f[maxn][];
vector<int> son[maxn]; void dfs(int x) {
f[x][] = ; //初始化 f[x][0]表示以x为根的子树,且x不参加舞会的最大快乐值
f[x][] = w[x]; //f[x][1]表示以x为根的子树,且x参加舞会的最大快乐值
for (int i = ; i < son[x].size(); i++) {
int y = son[x][i];
dfs(y);
f[x][] += max(f[y][], f[y][]); //状态转移方程
f[x][] += f[y][];
}
} int main() {
int n;
scanf("%d", &n);
for (int i = ; i <= n; i++) scanf("%d", &w[i]);
for (int i = ; i <= n - ; i++) {
int x, y;
scanf("%d%d", &x, &y); //注意父亲在后
son[y].push_back(x);
v[x]++;
}
int root;
for (int i = ; i <= n; i++) {
if (!v[i]) {
root = i; break;
}
}
dfs(root);
printf("%d\n", max(f[root][], f[root][]));
return ;
}
树上的常见操作
const int maxn = ;
vector<int> v[maxn];
int _size[maxn]; //结点大小
int mx_size[maxn];
int depth[maxn];
int Max[maxn];
int val[maxn]; void getsize(int x) { //一棵N个点的无权树,问每个结点的大小
_size[x] = ;
for (int i = ; i < v[x].size(); i++) {
getsize(v[x][i]);
_size[x] += _size[v[x][i]];
}
} void getdep(int x) { //一棵N个点的无权树,问每个结点的深度
for (int i = ; i < v[x].size(); i++) {
depth[v[x][i]] = depth[x] + ;
getdep(v[x][i]); //自顶向下
}
} void getmax(int x) { //一棵N个点的点权树,问每个子树的点权和,点权最大值
Max[x] = val[x];
for (int i = ; i < v[x].size(); i++) {
getmax(v[x][i]);
Max[x] = max(Max[x], Max[v[x][i]]);
}
}
求树的重心
定义:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡

C++代码
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<cmath>
const double PI = acos(-1.0);
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std; const int maxn = ;
int n, m, ans;
int len, lenp;
int _size[maxn], id[maxn], p[maxn];
vector<int> e[maxn];
bool vis[maxn]; int dfs(int x) {
if (!e[x].size()) return ;
int sum = ;
for (int i = ; i < e[x].size(); i++) {
if (!vis[e[x][i]]) {
vis[e[x][i]] = true;
sum += dfs(e[x][i]);
}
}
return sum;
} int main() {
scanf("%d", &n);
int x, y;
for (int i = ; i < n; i++) {
scanf("%d%d", &x, &y);
e[x].push_back(y);
}
for (int i = ; i <= n; i++) {
memset(vis, , sizeof vis);
vis[i] = ;
_size[i] = dfs(i);
}
int Min = INF;
for (int i = ; i <= n; i++) {
int Max = n - _size[i];
for (int j = ; j < e[i].size(); j++) Max = max(Max, _size[e[i][j]]);
Min = min(Max, Min);
p[i] = Max;
}
for (int i = ; i <= n; i++) {
if (p[i] == Min) {
lenp++;
id[lenp] = i;
}
}
printf("%d\n", lenp); //重心个数
for (int i = ; i <= lenp; i++) printf("%d\n", id[i]);
return ;
}
HZNU-ACM寒假集训Day10小结 树-树形DP的更多相关文章
- HZNU-ACM寒假集训Day10小结 单调栈-单调队列
数据结构往往可以在不改变主算法的前提下题高运行效率,具体做法可能千差万别,但思路却是有规律可循 经典问题:滑动窗口 单调队列O(n) POJ 2823 我开始写的: TLE 说明STL的库还是有点慢 ...
- 【BZOJ-3572】世界树 虚树 + 树形DP
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1084 Solved: 611[Submit][Status ...
- 【BZOJ-2286】消耗战 虚树 + 树形DP
2286: [Sdoi2011消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2120 Solved: 752[Submit][Status] ...
- 51nod 1353 树 | 树形DP经典题!
51nod 1353 树 | 树形DP好题! 题面 切断一棵树的任意条边,这棵树会变成一棵森林. 现要求森林中每棵树的节点个数不小于k,求有多少种切法. 数据范围:\(n \le 2000\). 题解 ...
- bzoj 2286(虚树+树形dp) 虚树模板
树链求并又不会写,学了一发虚树,再也不虚啦~ 2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5002 Sol ...
- 洛谷 P1453 城市环路 ( 基环树树形dp )
题目链接 题目背景 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域--城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环路之内便是B市 ...
- BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca
BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的 ...
- 中南大学2019年ACM寒假集训前期训练题集(基础题)
先写一部分,持续到更新完. A: 寒衣调 Description 男从戎,女守家.一夜,狼烟四起,男战死沙场.从此一道黄泉,两地离别.最后,女终于在等待中老去逝去.逝去的最后是换尽一生等到的相逢和团圆 ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...
随机推荐
- jumpserver手动配置文档
1.环境 centos7.6 硬盘 200G cpu 8核心 内存 32G (本地测试的时候,有报错,原因为虚拟机配置不够,此时为在pve虚拟化上面做的linux系统) 2.https:/ ...
- 关于ESP8266和ESP8285的对比
ESP8285=ESP8266+1M Flash. 与ESP8266相比,其能耐高温达125摄氏度!且原有ESP8266源码程序可以原封不动移植使用.ESP-M1/M2 模块核心处理器采用高性价比芯片 ...
- WAFの基本防护透明流模式v1.0
一.WAFの透明流模式 1)首先先配置WAF的网络,配置一个网桥接口,设置IP便于带内管理. 2)当然,如果需要不同网段之间都能够管 ...
- 项目启动报错:Communications link failure
2017-12-29 10:43:19,776 ERROR [com.alibaba.druid.pool.DruidDataSource] - <init datasource error, ...
- net Core3.1 Swagger加JWT权限
1.Swagger中开启JWT服务 #region swagger services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new ...
- 解决d7在更高版本上运行乱码问题,或者是调用更高版本的dll
将String类型改成WideString类型即可
- NIO 与 零拷贝
零拷贝介绍 零拷贝是网络编程的关键, 很多性能优化都需要零拷贝. 在 Java程序中, 常用的零拷贝方式有m(memory)map[内存映射] 和 sendFile.它们在OS中又是怎样的设计? NI ...
- A convenient way to recognize and handwrite multidimensional arrays in Numpy
As a new learner of Numpy, it is very common to be confused by the form of array, braces nested in b ...
- pyhton读入Excel和csv数据文件
pyhton读入Excel和csv数据文件#file 数据文件的输入输出操作(主要包括Excel表格和csv表格文件)import pandas as pd #pyhton读入数据必须要导入panda ...
- 吴裕雄--天生自然java开发常用类库学习笔记:List接口
import java.util.ArrayList ; import java.util.List ; import java.util.Collection ; public class Arra ...