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;
}

3.P2015 二叉苹果树

又是树形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;
}

  

4.4753: [Jsoi2016]最佳团体

因为找题的时候已经知道是二分了,一开始有点懵逼,然后突然想起世界上有种叫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的更多相关文章

  1. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  2. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  3. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  4. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  5. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

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

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

  7. POJ2342 树形dp

    原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...

  8. hdu1561 The more, The Better (树形dp+背包)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...

  9. bzoj2500: 幸福的道路(树形dp+单调队列)

    好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...

  10. BZOJ 1040 树形DP+环套树

    就是有n个点n条边,那么有且只有一个环那么用Dfs把在环上的两个点找到.然后拆开,从这条个点分别作树形Dp即可. #include <cstdio> #include <cstrin ...

随机推荐

  1. 移植 thttpd Web 服务器

    下载 从 http://www.acme.com/software/thttpd/下载 thttpd 到/tmp 目录当中,并解压. 编译 thttpd [arm@localhost thttpd­2 ...

  2. java 压缩包

    package com.gome.budget.common.utils; import org.apache.commons.compress.archivers.ArchiveEntry; imp ...

  3. C++ AOP手法

    1.代理模式 2.模版 3.NVI(non-virtual interface) 参考:https://www.cnblogs.com/qicosmos/p/4772389.html <effe ...

  4. 两个datagrid的数据移动(支持多选)

    1.需求 :点击卸车和撤销按钮可以实现 1和2 之间数据的移动(支持多选) 2. 代码 (这里只写一个撤销的功能) //撤销按钮 function moveOut() { var item = $(' ...

  5. 0817NOIP模拟测试赛后总结

    吐槽一句:话说NOIP都取消了还叫NOIP模拟真的好么 于是乎我再次爆炸……(0+20+50=70 rank26) 赛时状态 赛时的状态依旧不佳.不过还是硬逼着自己把三道题都读完,然后开始对出题人静坐 ...

  6. 自己整理的一个访问SQLite3数据库的C++类

    原文地址:自己整理的一个访问SQLite3数据库的C++类作者:vigra 近日,对SQLite3的使用进行了研究.真不愧是优秀的嵌入数据库,API接口也极其简捷.基本上只要使用以下几个接口就能完成数 ...

  7. JavaScrip中的循环语句

    循环语句 循环语句,也是流程控制语句中不可或缺的一种结构.在 JavaScrip中实现循环的方式有好几个一个来看 1.为什么需要循环 在具体介绍 Javascript中的循环之前,首先我们来明确一个问 ...

  8. Android基础控件RatingBar星级评分条的使用

    1.简介 RatingBar继承ProgressBar,除了ProgressBar的属性外还有特有属性: android:isIndicator:是否用作指示,用户无法更改,默认false andro ...

  9. 基础类型转化成String 转

    基础类型转化成String 在程序中你可能时常会需要将别的类型转化成String,有时候可能是一些基础类型的值.在拼接字符串的时候,如果你有两个或者多个基础类型的值需要放到前面,你需要显式的将第一个值 ...

  10. Python学习day18-常用模块之NumPy

    figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...