几个树形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 ...
随机推荐
- websocket 实现消息推送(转)
介绍 现很多网站为了实现即时通讯,所用的技术都是轮询(polling).轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客服端的浏览器. ...
- Android开发 MediaRecorder使用Camera2配合录制视频(暂时有异常抛出,无法使用)
前言 这个博客本来是用来详细介绍MediaRecorder与Camera2,但是出乎预料之外,在获取mMediaRecorder.getSurface();的时候无论如何都是报错的,报错为Surfac ...
- CodeForces - 27E
https://vjudge.net/problem/CodeForces-27E 求因子个数为n的最小的数dfs枚举质因子的幂 #include <iostream> #include ...
- Python-包与常用模块(2)
目录 包 导入包内包 相对导入和绝对导入 注意事项 time模块 datetime模块 random模块 argparse 模块 configparser模块 hashlib模块和hmac模块 typ ...
- Jdk8 Hashmap ConcurrentHashMap
JDK1.8 Hashmap JDK1.8 ConcurrentHashMap 不采用segment而采用 synchronized (f) f = table[i]; 减小锁的力度 设计了MOVE ...
- Docker系列(十二):Kubernetes的分布式网络实践
tip:本节课的学习视频没有找到,所以有的地方可能不是很清晰. 可选的几种网络方案 openvswitch 是一种主流的虚拟化大二层技术 灵活 对现有物理网络没要求 业界主流 软件封装导致性能低 复杂 ...
- 数论专场 Day9 部分题解
// 2019年西电暑期集训 // [7月9日]基础数论:https://cn.vjudge.net/contest/309097 A - Visible Lattice Points 题目大意: 平 ...
- Java室内最短路径搜索(支持多楼层)
修改了上次的代码,现在支持室内的多楼层情况下的最短路径搜索,还是使用A*算法,把在GraphAdjList中VNode没有利用起来的data字段作为我们存储楼层属性的位置. 实际上是我偷懒了,正常情况 ...
- 通过实体类生成建表SQL语句实现方法
import java.io.File; import java.io.FileOutputStream; import java.lang.reflect.Field; import java.ut ...
- Windows 系统文件夹目录挂载到 Linux服务器中
在Windows系统文件上传到Linux服务器时有时候很麻烦,因为Linux无界面的系统不像Windows系统一样,可以直接复制粘贴,下面方法可以解决Windows系统文件拷贝到Linux服务器. 1 ...