树形dp初步
其实很早之前就学过树形dp,今天总接一下。树形dp就是一个在树上跑的dp(滑稽)
先是一道板子题:树上最大独立集
直接上代码了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct node
{
int x,y,next;
};
node a[];
int len,last[];
void add(int x,int y)
{
a[++len].x = x;
a[len].y = y;
a[len].next = last[x];
last[x] = len;
}
int fa[],son[];
int f[][];
int v[];
/*
f[i][1]代表请i的最大值
f[i][0]代表不请i的最大值
*/
template <class T>
void read(T &x)
{
char c;
int op = ;
while(c = getchar(),c > '' || c < '')
if(c == '-') op = ;
x = c - '';
while(c = getchar(),c >= '' && c <= '')
x = x * + c - '';
if(op == )
x = -x;
}
void treedp(int x)
{
f[x][] = v[x];
for(int k = last[x];k;k = a[k].next) //相当于dfs
treedp(a[k].y);
for(int k = last[x];k;k = a[k].next)
{
int y = a[k].y;
f[x][] += f[y][]; //dp转移式①
}
f[x][] = ;
for(int k = last[x];k;k = a[k].next)
{
int y = a[k].y;
f[x][] += max(f[y][],f[y][]);//dp转移式②
}
}
int main()
{
int n;
read(n);
memset(f,-,sizeof(f));
memset(fa,,sizeof(fa));
for(int i = ;i <= n;i++)
read(v[i]);
int xx,yy;len = ;
memset(last,,sizeof(last));
while(scanf("%d%d",&xx,&yy) != EOF)
{
if(xx == && yy == )
{
break;
}
add(yy,xx);
fa[xx] = yy; //找根节点
}
int root = ;
for(int i = ;i <= n;i++)
if(fa[i] == )
{
root = i;
break;
}
treedp(root);
printf("%d\n",max(f[root][],f[root][]));
return ;
}
然后还有几个稍微比这个难一点的题,比如:加分二叉树
【问题描述】
设一个有n个节点的二叉树的中序遍历为(l,,,…,n),其中数字1,,,…,n为节点编号。
每个节点都有一个分数(均为正整数),记第i个节点的分数为di, 每棵子树都有一个加分,任一棵子树subtree的加分计算方法如下:
subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数
若某个子树为空,规定其加分为1,叶子的加分就是叶节点本身的分数。不考虑它的空子树。
试求一棵符合中序遍历为(,,,…,n)且加分最高的二叉树tree。要求输出;
()tree的最高加分
()tree的前序遍历
【输入格式】
第1行:一个整数n(n<),为节点个数。
第2行:n个用空格隔开的整数,为每个节点的分数(分数<)。
【输出格式】
第1行:一个整数,为最高加分(结果不会超过2, )。
第2行:n个用空格隔开的整数,为该树的前序遍历。
【样例输入】 【样例输出】
这个题需要枚举中间的断点,然后进行dp。dp比之前简单了,但是其他的要难一些。
#include<cstdio>
#include<iostream>
using namespace std;
int root[][],d[],f[][];
void pre_visit(int l,int r)
{
if(l <= r)
{
cout<<root[l][r]<<" ";
pre_visit(l,root[l][r] - );
pre_visit(root[l][r] + , r);
}
}
int main()
{
int m;
cin>>m;
for(int i = ;i <= m;i++)
{
for(int j = ;j <= m;j++)
{
f[i][j] = ;
}
}
for(int i = ;i <= m;i++)
{
cin>>d[i];
root[i][i] = i;
f[i][i] = d[i];
}
for(int k = ;k <= m;k++)
{
for(int l = ;l <= m - k + ;l++)
{
int r = l + k - ;
for(int i = l;i <= r;i++)
{
if(f[l][r] < f[l][i - ] * f[i + ][r] + d[i])
{
root[l][r] = i;
f[l][r] = f[l][i - ] * f[i + ][r] + d[i];
}
}
}
}
cout<<f[][m]<<endl;
cout<<root[][m]<<" ";
pre_visit(,root[][m] - );
pre_visit(root[][m] + ,m);
}
还有一个皇宫看守,和最大独立点集很像
【问题描述】
太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫。 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;有边直接相连的宫殿可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。 可是陆小凤手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。 编程任务:帮助陆小凤布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。
【输入格式】
输入文件中数据表示一棵树,描述如下:
第1行 n,表示树中结点的数目。
第2行至第n+1行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号i(<I<=N),在该宫殿安置侍卫所需的经费K,该点的儿子数M,接下来M个数,分别是这个节点的M个儿子的标号R1,R2,...,RM。对于一个n( < n<=)个结点的树,结点标号在1到n之间,且标号不重复。
【输出格式】
输出文件仅包含一个数,为所求的最少的经费。
输入样例: 输出样例:
这个题很好想。
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
struct node
{
ll x,y,next;
};
node a[];
ll v[],f[][];
ll last[],len = ;
bool bk[];
/*
i节点安全代表i节点和子树安全
不安全代表i节点不安全,但是子树安全
f[i][0]表示x点不放人,但是安全
f[i][1]表示x点不放人,不安全
f[i][2]表示x点放人,所以安全
f[i][3]表示x点放人,但是不安全,显然不成立
*/
void treedp(int x)
{
f[x][] = v[x];
f[x][] = ;f[x][] = ;
ll minn = ;
bool bkk = false;
for(int k = last[x];k;k = a[k].next)
{
ll y = a[k].y;
if(bk[y] == false)
{
bk[y] = true;
treedp(y);
minn = min(f[y][] - f[y][],minn);
f[x][] += min(f[y][],f[y][]);
if(f[y][] <= f[y][])
{
bkk = true;
}//一定选f[i][2]
f[x][] += f[y][];
f[x][] += min(f[y][],min(f[y][],f[y][]));
}
}
if(bkk == false)
{
f[x][] += minn;
}
}
void add(int x,int y)
{
a[++len].x = x;
a[len].y = y;
a[len].next = last[x];
last[x] = len;
}
int main()
{
ll n;
cin>>n;
memset(f,,sizeof(f));
for(int i = ;i <= n;i++)
{
ll x,m,k;
cin>>x>>k>>m;
v[x] = k;
for(int j = ;j <= m;j++)
{
ll y;
cin>>y;
add(x,y);
add(y,x);
}
}
ll root = ;
memset(bk,false,sizeof(bk));
bk[root] = true;
treedp(root);
cout<<min(f[root][],f[root][]);
return ;
}
树形dp初步的更多相关文章
- 洛谷P1122 最大子树和 树形DP初步
小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题.于是当日课后,小明就向老师提 ...
- 『没有上司的舞会 树形DP』
树形DP入门 有些时候,我们需要在树形结构上进行动态规划来求解最优解. 例如,给定一颗\(N\)个节点的树(通常是无根树,即有\(N-1\)条无向边),我们可以选择任意节点作为根节点从而定义出每一颗子 ...
- [提升性选讲] 树形DP进阶:一类非线性的树形DP问题(例题 BZOJ4403 BZOJ3167)
转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7337179.html 树形DP是一种在树上进行的DP相对比较难的DP题型.由于状态的定义多种多样,因此解法也五 ...
- 树形dp(A - Anniversary party HDU - 1520 )
题目链接:https://cn.vjudge.net/contest/277955#problem/A 题目大意:略 具体思路:刚开始接触树形dp,说一下我对这个题的初步理解吧,首先,我们从根节点开始 ...
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
- COGS 2532. [HZOI 2016]树之美 树形dp
可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...
- 【BZOJ-4726】Sabota? 树形DP
4726: [POI2017]Sabota? Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 128 Solved ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- 树形DP
切题ing!!!!! HDU 2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...
随机推荐
- Appium Python API 汇总
最近在学习Python自动化,网络搜集而来,留着备用, 方便自己也方便他人.感谢总结的人! 1.contexts contexts(self): Returns the contexts within ...
- 开发日记(项目中SQL查询的优化)
今天发现自己之前写的一些SQL查询在执行效率方面非常不理想,于是尝试做了些改进. 需求为查询国地税表和税源表中,国税有而税源没有的条目数,之前的查询如下: SELECT COUNT(NAME) ...
- JS——样式类的添加
1.注意current前有个空格 this.className = this.className + " current"; 2.直接将class所有的值替换成current th ...
- 【译】x86程序员手册04 - 2.2数据类型
2.2 Data Types 数据类型 Bytes, words, and doublewords are the fundamental data types (refer to Figure 2- ...
- 【sqli-labs】 less52 GET -Blind based -Order By Clause -numeric -Stacked injection(GET型基于盲注的整型Order By从句堆叠注入)
出错被关闭了 http://192.168.136.128/sqli-labs-master/Less-52/?sort=1' http://192.168.136.128/sqli-labs-mas ...
- js的一些老司机写法
//取整 parseInt(a,10); //Before Math.floor(a); //Before a>>0; //Before ~~a; //After a|0; //After ...
- LNMP动态网站架构及web应用部署,搭建discuz论坛
1)部署Nginx 实验tar安装包可找本人拿记得点+关注,感谢亲们支持,评论拿包 systemctl stop firewalld iptables -F setenforce 0 1)安装支持软件 ...
- mapbox-gl 使用ArcGISServer 发布的栅格切片
最近使用mapbox 进行数据化展现.刚好用到了超图平台在去三维系统,顺带就用超图平台发布了栅格切片,用来做底图,但是超图平台是试用的许可,栅格切片有SuperMap 的水印,实在不雅观. 在网上搜索 ...
- SDWC 2018 day5
望得分:100+100+100 实际得分:100+100+100 Problem 1 晨跑(running.cpp/c/pas)[题目描述]为了响应学校的号召,模范好学生王队长决定晨跑.不过由于种种原 ...
- postgresql数据库部署
运维开发技术交流群欢迎大家加入一起学习(QQ:722381733) 一.postgresql数据库部署 1.前往postgresql安装包的目录(这里我部署的是10.5的版本) [root@web1 ...