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. Spark中使用Java编程的常用方法

    原文引自:http://blog.sina.com.cn/s/blog_628cc2b70102w9up.html 一.初始化SparkContext System.setProperty(" ...

  2. lxml etree对存在的xml添加新节点,新节点没有排版格式化

    新添加的时候如果不做处理,是这个样子 要在解析xml加上 parser = etree.XMLParser(remove_blank_text=True)xml = etree.parse(major ...

  3. [转]Entity Framework教程(第二版)

    源起 很多年前刚毕业那阵写过一篇关于Entity Framework的文章,没发首页却得到100+的推荐.可能是当时Entity Framework刚刚发布介绍EF的文章比较少.一晃这么多年过去了,E ...

  4. Zuul的过滤器

    过滤器类型与请求生命周期:         Zuul中定义了4种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期         PRE: 这种过滤器在请求被路由之前调用.可利用这种过滤器实现身 ...

  5. swiper 插件里面嵌套可滚动内容

    在移动端使用swiper的整屏滚动,如果slide里面有滚动内容的话,滚动的时候会整个页面一起滚动,如果想里面的滚动区域单独滚动的话,可以在初始化swiper的时候添加上 noSwipingClass ...

  6. js声明变量的三种方式

    JS 声明变量的三种方式 (1)使用变量步骤:a.声明-->b.赋值-->3.调用 正确用法: <script type="text/javascript"> ...

  7. .Net StackFrame

    StackFrame指的是一个.net运行的时候堆栈上的一个帧(Frame),每次进入一个方法的时候就会有一个新的方法帧压入线程执行堆栈,可以通过StackFrame获取相关的信息,比如当前代码所在文 ...

  8. 表单下拉框select

    <!DOCTYPE html> <html lang="zh"> <head> <title></title> < ...

  9. Spring MVC(八)--控制器接受简单列表参数

    有些场景下需要向后台传递一个数组,比如批量删除传多个ID的情况,可以使用数组传递,数组中的ID元素为简单类型,即基本类型. 现在我的测试场景是:要从数据库中查询minId<id<maxId ...

  10. 《DSP using MATLAB》Problem 8.12

    代码: %% ------------------------------------------------------------------------ %% Output Info about ...