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)<= ...
随机推荐
- iOS Burp suite CA证书 HTTPS
设置好burp suite代理后,在浏览器地址输入http://burp/,下载CA证书: 在iOS上下载CA证书,可通过邮件或百度云等一切iOS可以访问证书文件的方法: 点击证书文件iOS提示安装, ...
- 转《Python爬虫学习系列教程》学习笔记
http://www.cnblogs.com/xin-xin/p/4297852.html
- 对S7通信的连接的理解以及对比CAN通信协议来理解PLC通讯
对S7通信的连接的理解以及对比CAN通信协议来理解PLC通讯. 对功能块 SFB12 和 SFB13 的R_ID参数的理解 ? 对于同一个数据包.发送方与接收方的R_ID应该相同. 用下图解释 双向连 ...
- 51nod 1444:破坏道路 广度优先搜索
1444 破坏道路 题目来源: CodeForces 基准时间限制:1.5 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 取消关注 在某一个国家,那儿有n个城市,他们通过 ...
- BGR to RGB排列
BGR to RGB排列 2012年09月27日 13:59:48 雷电羊 阅读数:4759 https://blog.csdn.net/cjsycyl/article/details/80247 ...
- Scala 线性化规则和 super 操作
如果一个类有多个父类,且父类的有相同的函数 f,在子类和父类中调用 super.f 都是按从右到左的调用函数的顺序. 这个规则名为:Linearization Rules 如下的代码 trait Ba ...
- 移动 web 开发问题和优化小结
1.前言 到目前为止,互联网行业里,手机越来越智能化,移动端占有的比例越来越高,尤其实在电商,新闻,广告,游戏领域.用户要求越来越高,网站功能越来越好,效果越来越炫酷,这就要求我们产品质量越来越高,w ...
- 《机学五》KNN算法及实例
一.概述 [定义]如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别. 二.距离计算公式 两个样本的距离可以通过如下公式计算,又叫[欧式距 ...
- P1001 害死人不偿命的(3n+1)猜想 (Basic Level)
转跳点:
- maven手动安装ojdbc6.jar包到本地仓库
需要jar文件 ojdbc6.jar jar下载地址1 下载地址2 本地执行: mvn install:install-file -Dfile=D:/ojdbc6.jar -DgroupId=co ...