树形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的更多相关文章

  1. HZNU-ACM寒假集训Day10小结 单调栈-单调队列

    数据结构往往可以在不改变主算法的前提下题高运行效率,具体做法可能千差万别,但思路却是有规律可循 经典问题:滑动窗口  单调队列O(n) POJ 2823 我开始写的: TLE 说明STL的库还是有点慢 ...

  2. 【BZOJ-3572】世界树 虚树 + 树形DP

    3572: [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1084  Solved: 611[Submit][Status ...

  3. 【BZOJ-2286】消耗战 虚树 + 树形DP

    2286: [Sdoi2011消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2120  Solved: 752[Submit][Status] ...

  4. 51nod 1353 树 | 树形DP经典题!

    51nod 1353 树 | 树形DP好题! 题面 切断一棵树的任意条边,这棵树会变成一棵森林. 现要求森林中每棵树的节点个数不小于k,求有多少种切法. 数据范围:\(n \le 2000\). 题解 ...

  5. bzoj 2286(虚树+树形dp) 虚树模板

    树链求并又不会写,学了一发虚树,再也不虚啦~ 2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5002  Sol ...

  6. 洛谷 P1453 城市环路 ( 基环树树形dp )

    题目链接 题目背景 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域--城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环路之内便是B市 ...

  7. BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca

    BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的 ...

  8. 中南大学2019年ACM寒假集训前期训练题集(基础题)

    先写一部分,持续到更新完. A: 寒衣调 Description 男从戎,女守家.一夜,狼烟四起,男战死沙场.从此一道黄泉,两地离别.最后,女终于在等待中老去逝去.逝去的最后是换尽一生等到的相逢和团圆 ...

  9. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

随机推荐

  1. sklearn实现多分类逻辑回归

    sklearn实现多分类逻辑回归 #二分类逻辑回归算法改造适用于多分类问题1.对于逻辑回归算法主要是用回归的算法解决分类的问题,它只能解决二分类的问题,不过经过一定的改造便可以进行多分类问题,主要的改 ...

  2. VS中MFC项目文件特别大的解决办法

    转 来自http://m.zhizuobiao.com/vc/vc-18082800177/ 自己插个眼 项目文件比较大因为 项目下有个隐藏文件夹.vs  下面是解决办法 本文主要向大家介绍了VC编程 ...

  3. CrossOriginFilter

    当使用jQuery Ajax post请求时可能会遇到类似这样的错误提示 XMLHttpRequest cannot oad http://xxxxxx. Origin http://xxxxxx i ...

  4. 吴裕雄--天生自然JAVAIO操作学习笔记:RandomAccessFile

    import java.io.File ; import java.io.RandomAccessFile ; public class RandomAccessFileDemo01{ // 所有的异 ...

  5. 洛谷P2089 烤鸡

    标签:暴力,枚举 题目背景 猪猪 Hanke 得到了一只鸡. 题目描述 猪猪 Hanke 特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke 吃鸡很特别,为什么特别呢?因为他有 10 种配料(芥末. ...

  6. centos搭建gitlib

    sudo yum install -y curl policycoreutils-python openssh-server sudo yum -y install postfixsudo syste ...

  7. Day 29:HTML常用标签

    软件的结构:  cs结构的软件的缺点:更新的时候需要用户下载更新包然后再安装,需要开发客户端与服务端.  cs结构软件的优点: 减轻服务端的压力,而且可以大量保存数据在客户端.  C/S(Client ...

  8. Golang的选择结构-switch语句

    Golang的选择结构-switch语句 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.选择语句应用场景概述 选择结构也称为条件判断,生活中关于判断的场景也非常的多,比如: ( ...

  9. CAN分帧发送程序说明

    试验平台 仅仅 需要一台主机 一台 周立功 CAN 助手, 一个232 助手就OK ICAN 协议 资源节点地址 电脑 我认为是0x01 51单片机主机的地址 是 0x1f 建立连接的 功能码 是0x ...

  10. flask邮箱注册问题

    app/models.py self.confirmed = True db.session.add(self) db.session.commit() 这里的数据修改完后必须commit提交上去,不 ...