几个树形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 ...
随机推荐
- LeetCode 237. 删除链表中的节点(Python3)
题目: 请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点. 现有一个链表 -- head = [4,5,1,9],它可以表示为: 示例 1: 输入: head ...
- 进程互斥软件实现之Lamport面包店算法
一. 进程互斥的实现方式 1. 软件方式: 保护临界区, 自己编写代码来实现对进程的控制. Dekker算法Peterson算法Lamport算法等 2. 硬件方式: 使用特殊指令保护临界区. 开关中 ...
- 【JZOJ2288】【BZOJ1898】【luoguP2579】沼泽鳄鱼
description 潘塔纳尔沼泽地号称世界上最大的一块湿地,它地位于巴西中部马托格罗索州的南部地区.每当雨季来临,这里碧波荡漾.生机盎然,引来不少游客. 为了让游玩更有情趣,人们在池塘的中央建设了 ...
- php中$_REQUEST、 $_GET、 $_POST、 $_COOKIE 的关系和区别
看到REQUEST可以通吃GET .POST .COOKIE 后 感觉这个$_REQUEST太强大了是不是其他的几个超级变量就没有用了,下面对他们整体做个比较: 1.安全性 post>get 2 ...
- 19-11-10-Night
关于$Miemeng$,它死了. 大家有没有记得我在暑假里曾经写过一个著名模数? const int Mod=998224353; 现在有续集了(捂脸)(改不过题.jpg) const int Mod ...
- 表单下拉框select
<!DOCTYPE html> <html lang="zh"> <head> <title></title> < ...
- java单元测试小结
1. mock 构造函数 import static org.junit.Assert.*; import java.util.ArrayList; import org.junit.Test; im ...
- mysql之sql优化
sql的执行顺序: 先看下下面两条多表关联sql,第1条查询到1条记录,第2条查无记录: on 筛选条件在笛卡尔积之前,where筛选条件在笛卡尔积之后执行 先执行from, join的话,左连接,左 ...
- Django的日常-路由层
目录 Django的日常-2 路由层 有名分组和无名分组 反向解析 路由的分发 Django的日常-2 路由层 我们之前已经接触过路由层,只是我们可能不知道他叫这个名字,实际上在Django里面路由层 ...
- VRRP概述-转
本文介绍了VRRP的基本原理.特点和应用. VRRP概述 随着Internet的发展,人们对网络的可靠性的要求越来越高.对于局域网用户来说,能够时刻与外部网络保持联系是非常重要的. 通常情况下,内部网 ...