蒟蒻的树形dp记录
POJ2342:
题意:某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知每个人的活跃指数和上司关系(当然不可能存在环),求邀请哪些人(多少人)来能使得晚会的总活跃指数最大。
题解:
当i来的时候,dp[i][1] += dp[j][0];//j为i的下属
当i不来的时候,dp[i][0] +=max(dp[j][1],dp[j][0]);//j为i的下属
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <typeinfo>
#include <map>
//#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
#define inf 10000000
inline ll read()
{
ll x=,f=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-')f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
//*************************************************************** int dp[][];
int vis[];
int parent[];
int n,a,b;
void sp(int x)
{
vis[x]=;
for(int i=;i<=n;i++)
{
if(parent[i]==x&&!vis[i])
{
sp(i);
dp[x][]+=max(dp[i][],dp[i][]);
dp[x][]+=dp[i][];
}
}
}
int main()
{ while(cin>>n)
{ memset(dp,,sizeof(dp));
for(int i=;i<=n;i++)
scanf("%d",&dp[i][]);
memset(vis,,sizeof(vis)); int root=;
memset(parent,,sizeof(parent));
while(scanf("%d%d",&a,&b)&&a&&b)
{
parent[a]=b;
root=b;
}
sp(root);
printf("%d\n",max(dp[root][],dp[root][]));
}
return ;
}
代码狗
vijos1642
题解:我们先依次求出每棵树的先根遍历序,并保存在同一个序列list[]中。 为了利用上面的结论,我们还要求出以节点i为根的子树的节点总数count[i]。
定义: v[i]表示第i个物品的权值 dp[i][j]表示从第i个物品到第n个物品,最多花费j,能得到的最大权值和。
状态转移: 对于一个节点,我们考虑是否购买它: 购买:那么我们继续考虑它后面的节点 不购买:那么我们跳过它的子孙节点
方程如下: F[i][j]=Max{F[i+1][j-cost[list[i]]]+weight[list[i]],F[i+count[list[i]]][j]}
///
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <typeinfo>
#include <map>
typedef long long ll;
using namespace std;
#define inf 10000000
inline ll read()
{
ll x=,f=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-')f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
//***************************************************************
///先根遍历序
int list[];
int s[],a[][];
int v[],counts[];
int dp[][];
int q;
int n,m;
int dfs(int k)
{
list[++q]=k;
if(s[k]==){return ++counts[k];}
for(int i=;i<=s[k];i++)
{
counts[k]+=dfs(a[k][i]);
}
return ++counts[k];
}
int main()
{
int t;
memset(dp,-,sizeof(dp));
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{ scanf("%d%d",&v[i],&t);
while(t--)
{
scanf("%d",&a[i][++s[i]]);
}
}
dfs();
for(int i=;i<=n;i++){dp[i][]=;dp[i][]=v[list[i]];}
for(int i=n-;i>=;i--)
{
for(int j=;j<=m;j++)
{
dp[i][j]=max(dp[i+][j-]+v[list[i]],dp[i+counts[list[i]]][j]);
}
}
int ans=-inf;
for(int i=;i<=m;i++)
ans=max(dp[][i],ans);
printf("%d\n",max(ans,));
return ;
}
代码狗
POJ 1947
题解:dp[root][i]表示以root为根得到节点数为i 所需要删除的少边数
转移:
dp[root][i]=dp[root][i]+1; 不加某son,边+1;
dp[root][i]=min(dp[root][i-j]+dp[son][j]);加某son,j代表son为根的树节点数
最后注意:非根节点边数+1;因为要删除与父亲节点的边
///
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <typeinfo>
#include <map>
typedef long long ll;
using namespace std;
#define inf 10000000
inline ll read()
{
ll x=,f=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-')f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
//***************************************************************
int dp[][];
vector<int >son[];
int dfs(int root,int pre)
{
dp[root][]=;
int sum=;
for(int i=;i<son[root].size();i++)
{
int s=son[root][i];
if(s==pre)continue;
sum+=dfs(s,root);
for(int k=sum;k>=;k--)
{
dp[root][k]=dp[root][k]+;
for(int h=;h<k;h++)
{
dp[root][k]=min(dp[root][k],dp[root][k-h]+dp[s][h]);
}
}
}
return sum;
}
int main()
{
int n,m,a,b;
memset(dp,,sizeof(dp));
scanf("%d%d",&n,&m);
// for(int i=1;i<=n;i++)dp[i][0]=1;
for(int i=;i<n;i++)
{
scanf("%d%d",&a,&b);
son[a].push_back(b);
son[b].push_back(a);
}
dfs(,-);
int ans=dp[][m];
for(int i=;i<=n;i++){
if(dp[i][m]+<ans)ans=dp[i][m]+;
}
printf("%d\n",ans);
return ;
}
代码
HDU 1011 Starship Troopers
转移:dp[i][k] = max(dp[i][k], dp[i][k-l] + dp[i][l]);
//зїеп:1085422276
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <typeinfo>
#include <map>
#include <stack>
typedef long long ll;
#define inf 100000000
using namespace std; inline ll read()
{
ll x=,f=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-')f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
//***************************************
int v[];
int cost[];
int dp[][];
vector<int >tr[];
int n,m;
void dfs(int k,int pre)
{
for(int i=cost[k];i<=m;i++)
dp[k][i]=v[k];
for(int i=;i<tr[k].size();i++){
if(pre==tr[k][i])continue;
dfs(tr[k][i],k);
int son=tr[k][i];
for(int j=m;j>=cost[k];j--)
{
for(int l=;l+cost[k]<=j;l++)
{
dp[k][j]=max(dp[k][j],dp[son][l]+dp[k][j-l]);
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==-&&m==-)break;
// init();
memset(dp,,sizeof(dp));
for(int i=;i<=n;i++)
{
scanf("%d%d",&cost[i],&v[i]);
cost[i]=cost[i]/+(cost[i]%!=);
// if(cost[i]%20!=0)cost[i]+=1;
tr[i].clear();
}
int a,b;
for(int i=;i<n;i++)
{
scanf("%d%d",&a,&b);
tr[a].push_back(b);
tr[b].push_back(a);
}
if(m==){printf("0\n");continue;}
dfs(,-);
printf("%d\n",dp[][m]);
}
return ;
}
代码
CodeForces 161D Distance in Tree
题目链接:http://codeforces.com/contest/161/problem/D
简单树形dp:维护各个节点1到k的情况就可以了;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <typeinfo>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
inline ll read()
{
ll x=,f=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-')f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
//**************************************************************************************
ll ans,dp[][];///以i为节点构成路径长度为j的种类树;
vector<int >G[];
int fa[];
int vis[];
int n,m;
void dfs(int k)
{
dp[k][]=;
for(int i=;i<G[k].size();i++){
int son=G[k][i];
if(vis[son])continue;
vis[son]=;
dfs(son);
for(int j=;j<m;j++){
ans+=dp[k][m-j-]*dp[son][j];
}
for(int i=;i<=m;i++)
{
dp[k][i]+=dp[son][i-];
}
}
} int main()
{ scanf("%d%d",&n,&m);
int a,b;
for(int i=;i<n;i++){
scanf("%d%d",&a,&b);
G[a].push_back(b);
G[b].push_back(a);
}
memset(vis,,sizeof(vis));
memset(dp,,sizeof(dp));
vis[]=;
dfs(); cout<<ans<<endl;
return ;
}
代码
【tyvj1520】树的直径
题目链接:http://www.tyvj.cn/p/1520
dp1[],dp2[]分别代表从当前根节点出发所能到达的最长链与次长链,感谢HZWER指点;。。。。。
///
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <typeinfo>
#include <map>
typedef long long ll;
using namespace std;
#define inf 10000000
inline ll read()
{
ll x=,f=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-')f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
//*************************************************************** struct ss
{
int to,next,v;
}e[*];
int head[],t,dp1[],dp2[],ans;
void add(int u,int v,int w)
{
e[t].to=v;
e[t].next=head[u];
e[t].v=w;
head[u]=t++;
}
void dp(int x,int pre)
{
for(int i=head[x];i;i=e[i].next)
{
if(e[i].to==pre)continue;
dp(e[i].to,x);
if(dp1[e[i].to]+e[i].v>dp1[x])
{
dp2[x]=dp1[x];
dp1[x]=dp1[e[i].to]+e[i].v;
}
else dp2[x]=max(dp1[e[i].to]+e[i].v,dp2[x]);
}
ans=max(dp1[x]+dp2[x],ans);
}
int main()
{int n;
memset(head,,sizeof(head));
t=;
ans=;
int u,v,w;
scanf("%d",&n);
for(int i=;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
dp(,);
cout<<ans<<endl; return ;
}
代码
蒟蒻的树形dp记录的更多相关文章
- 蒟蒻的数位DP专题总结
BZOJ 1026: [SCOI2009]windy数: 题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1026 d ...
- 蒟蒻所见之DP
本文有错是正常的,因为这只是一部成长史,并非教学博文. 会常年更下去. 2019.10.24 DP,核心只是"表格法"而已. DP题真正所考察的,是: 1.对问题的描述.简化以及归 ...
- 一个蒟蒻的解题过程记录——洛谷P1003 铺地毯
这到题算是我“火线回归”后码的第一道题,病好了心情不错,发篇博客分享一下 目录: ·题目描述 ·题目分析 ·解题思路 ·代码实现 ·总结 ·题目描述: 为了准备一场特殊的颁奖典礼,组织者在会场的一片矩 ...
- Codeforces 804D Expected diameter of a tree(树形DP+期望)
[题目链接] http://codeforces.com/contest/804/problem/D [题目大意] 给你一个森林,每次询问给出u,v, 从u所在连通块中随机选出一个点与v所在连通块中随 ...
- DP——由蒟蒻到神犇的进阶之路
开始更新咯 DP专题[题目来源BZOJ] 一.树形DP 1.bzoj2286消耗战 题解:因为是树形结构,一个点与根节点不联通,删一条边即可, 于是我们就可以简化这棵树,把有用的信息建立一颗虚树,然后 ...
- 蒟蒻关于斜率优化DP简单的总结
斜率优化DP 题外话 考试的时候被这个玩意弄得瑟瑟发抖 大概是yybGG的Day4 小蒟蒻表示根本不会做..... 然后自己默默地搞了一下斜率优化 这里算是开始吗?? 其实我讲的会非常非常非常简单,, ...
- 【杂文】CSP2019蒟蒻AFO(假)记
[杂文]CSP2019蒟蒻AFO(假)记 [初赛前 N 天] 时间:2019-10-15 今晚 \(2012\) 的初赛题做到心态爆炸,选择考计算机基础知识一脸懵逼,填空和后面一道大模拟直接跳过,最后 ...
- 【动态规划】树形DP完全详解!
蒟蒻大佬时隔三个月更新了!!拍手拍手 而且是更新了几篇关于DP的文章(RioTian狂喜) 现在赶紧学习和复习一下树形DP.... 树形DP基础:Here,CF上部分树形DP练习题:Here \[QA ...
- 树形DP习题
听闻noip要考树形DP,本蒟蒻万分惶恐,特刷一坨题目,以慰受惊之心. codevs 1486 /*和非常出名的"选课"是一个题*/ #include<cstdio> ...
随机推荐
- C# 类型参数的约束
在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制.如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误.这些限制称为约束.约束是使用 where 上 ...
- iOS-AFN "Request failed: unacceptable content-type: text/plain"
今天使用AFN测试程序时,返回如下错误 这是由于AFN默认不支持http返回结果为"text/plain"这种类型所致. 解决办法: 找到AFN框架中的AFURLResponseS ...
- php一些常用函数的理解
mysql_result($res, $row, [$field=0])是获取查询结果集中的 某一个 单元的内容. 其中, $row是行偏移, $field是列偏移, 或者叫索引, 都是从0开始的. ...
- yum只下载而不安装软件包?
yum本身自带了两个选项, 用来只下载要安装的rpm包, 而并不实际安装包: yum --downloadonly --downloaddir=/root/Desktop rpm-name1 rpm ...
- linux 中文件夹的文件按照时间倒序或者升序排列
1,按照时间升序 命令:ls -lrt 详细解释: -l use a long listing format 以长列表方式显示(详细信息方式) -t sort by modification time ...
- du: fts_read 失败: 无法分配内存
今天在查看一个大的文件时突然报出一个du: fts_read 失败: 无法分配内存的错误. 用 ulimit -a 查看下 core file size (blocks, -c) 0 data seg ...
- GNU make 升级
网上下载新版本的make文件后 在make目录下 ./configure make make install mv make /opt/mv_pro_5.0.0/montavista/common/b ...
- The content of element type "package" must match "(result-types?,interceptors?...
错误:“The content of element type "package" must match "(result-types?,interceptors?,de ...
- 2015安徽省赛 A.First Blood
题目描述 盖伦是个小学一年级的学生,在一次数学课的时候,老师给他们出了一个难题: 老师给了一个正整数 n,需要在不大于n的范围内选择三个正整数(可以是相同的),使它们三个的最小公倍数尽可能的大.盖伦很 ...
- Linux 面试题总结
一. 填空题1. 在Linux系统中,以 (文件) 方式访问设备 .2. Linux内核引导时,从文件 (/etc/fstab) 中读取要加载的文件系统.3. Linux文件系统中每个文件用 (索引节 ...