几个树形dp
1.重建道路
树形dp基础题,f[i][j]表示在i这个点我和我的子树联通块大小为j最少砍几条边。
转移的时候,到下一个子树时上一个子树所有答案先++(此树直接砍掉不贡献答案),再继续dp。
注意更新答案时,如果不是跟答案还有+1(砍掉我和我父亲的),不然洛谷会挂四个点QAQ
马上就Noip了我还只能做这种水题QAQ 还挂
//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<ctime>
typedef long long LL;
using namespace std;
const int N=201;
int ans,dp[N][N],n,p; template<typename T> void read(T &x) {
char ch=getchar(); T f=1; x=0;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
} int ecnt,fir[N],nxt[N<<1],to[N<<1];
void add(int u,int v) {
nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
} void dfs(int x,int fa) {
dp[x][1]=0;
for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
int y=to[i];
dfs(y,x);
for(int j=p;j>=1;j--) {
dp[x][j]++;
for(int k=0;k<j;k++)
dp[x][j]=min(dp[x][j],dp[x][j-k]+dp[y][k]);
}
}
if(x==1) ans=min(ans,dp[x][p]);
else ans=min(ans,dp[x][p]+1);
} void work() {
ans=1e9+7;
memset(dp,127/3,sizeof(dp));
dfs(1,0);
printf("%d\n",ans);
} void init() {
read(n); read(p);
for(int i=1;i<n;i++) {
int x,y;
read(x); read(y);
add(x,y);
}
} int main() {
#ifdef DEBUG
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif
init();
work();
return 0;
}
2.P2014 选课
树形dp水题。
dp[i][j]表示在i这个点,在我和我的儿子中选了j门课的最大学分。注意转移时若i!=0自己必须选,所以枚举我儿子选的课必须小于我和我儿子选的所有课,而i==0时则小于等于都ok。
//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<ctime>
typedef long long LL;
using namespace std;
const int maxn=307;
int n,m,dp[maxn][maxn],f[maxn],v[maxn]; template<typename T> void read(T &x) {
char ch=getchar(); T f=1; x=0;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
} int ecnt,fir[maxn],nxt[maxn],to[maxn],ans;
void add(int u,int v) {
nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
} void dfs(int x) {
dp[x][1]=v[x];
for(int i=fir[x];i;i=nxt[i]) {
int y=to[i];
dfs(y);
for(int j=m;j>=0;j--)
for(int k=0;k<=(j-(x!=0));k++)
dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[y][k]);
}
ans=max(ans,dp[x][m]);
} void work() {
dfs(0);
printf("%d\n",ans);
} void init() {
read(n);
read(m);
for(int i=1;i<=n;i++) {
read(f[i]);
read(v[i]);
add(f[i],i);
}
} int main() {
#ifdef DEBUG
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif
init();
work();
return 0;
}
又是树形dp水题。。
跟上面两个没啥差,还是最简单的。没啥可说了。
好水呀。。
//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<ctime>
typedef long long LL;
using namespace std;
const int maxn=100;
int n,m,dp[maxn][maxn]; template<typename T> void read(T &x) {
char ch=getchar(); T f=1; x=0;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
} int ecnt,fir[maxn],nxt[maxn<<1],to[maxn<<1],val[maxn<<1],ans;
void add(int u,int v,int w) {
nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=w;
} void dfs(int x,int fa) {
for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
int y=to[i];
dfs(y,x);
for(int j=m;j>=0;j--)
for(int k=0;k<j;k++)
dp[x][j]=max(dp[x][j],dp[x][j-k-1]+dp[y][k]+val[i]);
}
} void work() {
dfs(1,0);
printf("%d\n",dp[1][m]);
} void init() {
read(n);
read(m);
for(int i=1;i<n;i++) {
int x,y,z;
read(x);
read(y);
read(z);
add(x,y,z);
}
} int main() {
#ifdef DEBUG
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif
init();
work();
return 0;
}
因为找题的时候已经知道是二分了,一开始有点懵逼,然后突然想起世界上有种叫01分数规划的东西,然后树形dp就ok了。
这个看起来是n^3的dp实际上似乎是n^2的,然后bzoj加了一组数据后先sz[x]+=sz[y]再转移就过不了了,然后改一下就卡过了。
//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<ctime>
#define eps 1e-4
typedef long long LL;
using namespace std;
const int maxn=2507;
int n,m,b[maxn],a[maxn],f[maxn];
double l,r=10000,dp[maxn][maxn]; template<typename T> void read(T &x) {
char ch=getchar(); T f=1; x=0;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
} int ecnt,fir[maxn],nxt[maxn],to[maxn],sz[maxn];
void add(int u,int v) {
nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
} void dfs(int x,double now) {
if(x) dp[x][1]=(double)a[x]-(double)b[x]*now;
if(x!=0) sz[x]=1;
else sz[x]=0;
dp[x][0]=0;
for(int i=fir[x];i;i=nxt[i]) {
int y=to[i];
dfs(y,now);
for(int j=sz[x];j>=(x!=0);j--) {
for(int k=0;k<=sz[y];k++)
dp[x][j+k]=max(dp[x][j+k],dp[x][j]+dp[y][k]);
}
sz[x]+=sz[y];
}
} void work() {
while(r-l>=eps) {
double mid=(l+r)/2;
memset(dp,0xc2,sizeof(dp));
dfs(0,mid);
if(dp[0][m]>=eps) l=mid;
else r=mid;
}
printf("%.3lf\n",l);
} void init() {
read(m);
read(n);
for(int i=1;i<=n;i++) {
read(b[i]);
read(a[i]);
read(f[i]);
add(f[i],i);
}
} int main() {
#ifdef DEBUG
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif
init();
work();
return 0;
}
几个树形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 ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...
- POJ2342 树形dp
原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...
- hdu1561 The more, The Better (树形dp+背包)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...
- bzoj2500: 幸福的道路(树形dp+单调队列)
好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...
- BZOJ 1040 树形DP+环套树
就是有n个点n条边,那么有且只有一个环那么用Dfs把在环上的两个点找到.然后拆开,从这条个点分别作树形Dp即可. #include <cstdio> #include <cstrin ...
随机推荐
- jQuery插件编写,
jQuery插件编写 jQuery插件 最近搞jquery插件的编写这里做下笔记 给jquery扩展的方式很多,看的我眼花缭乱 方式1 $.fun=function(){} 方式2 $.fn.fun= ...
- [转]Entity Framework教程(第二版)
源起 很多年前刚毕业那阵写过一篇关于Entity Framework的文章,没发首页却得到100+的推荐.可能是当时Entity Framework刚刚发布介绍EF的文章比较少.一晃这么多年过去了,E ...
- golang和python的二进制转换
1.二进制转换规则 比如13,对13整除2,余数1,整除变为6,依次类推 13/2=6余1 6/2=3余0 3/2=1余1 1/2=0余1 所以最后的结果为1101 2.python def conv ...
- springboot指定项目访问路径前缀
springboot默认的运行方式是没有项目前缀的 如果这时候我们要加上调试或者发布,可以使用下面的方法加上 方法:
- P1985 [USACO07OPEN]翻转棋
题目链接: 翻转棋 题目分析: 先状压/\(dfs\)枚举第一排状态,然后在每个\(1\)下面翻,即确定了第一排就确定了后面的状态 最后验证一下最后一排是不是全0即可 代码: #include< ...
- 深入浅出 Java Concurrency (35): 线程池 part 8 线程池的实现及原理 (3)[转]
线程池任务执行结果 这一节来探讨下线程池中任务执行的结果以及如何阻塞线程.取消任务等等. 1 package info.imxylz.study.concurrency.future;2 3 publ ...
- SpringBoot学习笔记(二):SpringBoot访问静态文件、捕获全局异常、集成Thymeleaf、集成JSP
SpringBoot访问静态文件 什么是静态文件? 不需要通过web容器去得到的文件,直接通过路径就能得到的文件,比如项目的css,js,img等文件. 所有的资源文件都应该在src/main/res ...
- 深度学习(二十六)Network In Network学习笔记
深度学习(二十六)Network In Network学习笔记 Network In Network学习笔记 原文地址:http://blog.csdn.net/hjimce/article/deta ...
- 05.Hibernate常用的接口和类---Configuration类和作用
Configuration作用: 加载Hibernate配置文件,可以获取SessionFactory对象 加载方式: 1.加载配置文件 Configuration configuration = n ...
- vue题目
1.active-class是哪个组件的属性?嵌套路由怎么定义?答:vue-router模块的router-link组件. 2.怎么定义vue-router的动态路由?怎么获取传过来的动态参数? 答: ...