题解在代码中

二叉苹果树[loj 10153]

/*
若要留q条边便是要留q+1个点
所以记忆化搜索
dp[pos][ans]=max(dp[pos][ans],dp[l[pos]][k]+dp[r[pos]][ans-k-1]+a[pos])
0<=k<=ans-1
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
int n,q;
int book[][],a[],l[],r[];
void dfs(int pos){
for(int i=;i<=n;i++)
{
if(book[pos][i]!=-)
{
a[i]=book[pos][i];
book[pos][i]=-;book[i][pos]=-;
l[pos]=i;
dfs(i);
break;
}
}
for(int i=;i<=n;i++)
{
if(book[pos][i]!=-)
{
a[i]=book[pos][i];
book[pos][i]=-;book[i][pos]=-;
r[pos]=i;
dfs(i);
break;
}
}
return;
}
int dp[][];
int solve(int pos,int ans)
{
if(ans==) return ;
if(dp[pos][ans]!=-) return dp[pos][ans];
if(r[pos]==&&l[pos]==) return a[pos];
for(int j=;j<=ans-;j++)
dp[pos][ans]=max(dp[pos][ans],solve(l[pos],j)+solve(r[pos],ans--j)+a[pos]);
return dp[pos][ans]; }
int main()
{
memset(dp,-,sizeof(dp));
memset(book,-,sizeof(book));
n=read(),q=read();
for(int i=;i<n;i++)
{
int u=read(),v=read(),w=read();book[u][v]=w;book[v][u]=w;
}
dfs();
cout<<solve(,q+);
}

选课[loj 10154]

/*
建立一个虚根0使得将森林转化成为树
dp[i][j]表示为以i为根的子树下最多选j门课的最大学分
dfs后先进行背包处理
这是先不考虑先修课
再将有先修课 (pos!=0)时dp的容积为容积-1的最大值加上选修此门课的积分
dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[son][k])
j (m~0)
k(j~0)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
int n,m;
struct node{
int u,v,nex;
}x[];
int s[];
int t,cnt;
int dp[][],head[];
void add(int u,int v)
{
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
void dfs(int pos)
{
for(int p=head[pos];p!=-;p=x[p].nex)
{
int xx=x[p].v;
dfs(xx);
for(int i=m;i>=;i--)
for(int j=i;j>=;j--) dp[pos][i]=max(dp[pos][i],dp[pos][i-j]+dp[xx][j]);
}
if(pos!=)
{
for(int i=m;i>=;i--) dp[pos][i]=dp[pos][i-]+s[pos];
} // for(int i=m;i>=0;i--) cout<<"位置:"<<pos<<" 选课:"<<i<<" dp:"<<dp[pos][i]<<endl;
// system("pause");
return ;
}
int main()
{
memset(head,-,sizeof(head));
n=read(),m=read();
for(int i=;i<=n;i++)
{
t=read(),s[i]=read();
add(t,i);
}
dfs();
cout<<dp[][m];
}

数字转换[loj 10155]

/*
先预处理好因数和,再建一棵树
求树的最长链即可
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#pragma GCC optimize(2)
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
long long n,cnt;
struct node{
long long u,v,nex;
}x[];
long long head[];
long long dp1[],dp2[];
void add(long long u,long long v)
{
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
long long sum[];
long long maxn,book[];
//dp1表示最长,dp2表次长
void dfs(long long pos)
{
// cout<<pos<<endl;
for(long long i=head[pos];i!=-;i=x[i].nex)
{
long long p=x[i].v;
if(book[p]==)
{
book[p]=;
dfs(p);
if(dp1[p]+>dp1[pos]) dp2[pos]=dp1[pos],dp1[pos]=dp1[p]+;
else if(dp1[p]+>dp2[pos]) dp2[pos]=dp1[p]+;
maxn=max(maxn,dp1[pos]+dp2[pos]);
}
}
}
int main()
{
memset(head,-,sizeof(head));
n=read();
for(int i=;i<=n/;i++)
{
for(int j=i*;j<=n;j+=i)
{
sum[j]+=i;
}
}
for(int i=;i<=n;i++)
if(sum[i]<i) add(sum[i],i),add(i,sum[i]);
book[]=;
dfs();
cout<<maxn;
}

战略游戏[loj 10156]

/*
0为不选,1为选
pos的子孙为x
dp[pos][0]=sum(dp[x][1])
dp[pos][1]=sum(min(dp[x][0],dp[x][1]));
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
struct node{
int u,v,nex;
}x[];
int head[],n,cnt,dp[][],book[];
void add(int u,int v)
{
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
void dfs(int pos)
{
// cout<<pos<<endl;
dp[pos][]=;
for(int i=head[pos];i!=-;i=x[i].nex)
{
int p=x[i].v;
if(book[p]==)
{
book[p]=;
dfs(p);
dp[pos][]+=dp[p][];
dp[pos][]+=min(dp[p][],dp[p][]);
// cout<<pos<<" "<<dp[pos][0]<<" "<<dp[pos][1]<<" "<<endl;
}
}
}
int main()
{
memset(head,-,sizeof(head));
n=read();
for(int i=;i<=n;i++)
{
int t=read(),k=read();
for(int j=;j<=k;j++)
{
int p=read();
add(t,p),add(p,t);
}
}
book[]=;
dfs();
cout<<min(dp[][],dp[][]);
}

皇宫看守[loj 10157]

/*
dp[pos][0]为pos自己安放
dp[pos][1]为pos被自己的父亲看到
dp[pos][2]为pos被自己的子孙看到 dp[pos][0]+=min(dp[x][0],dp[x][1],dp[x][2])
dp[pos][1]+=min(dp[x][0],dp[x][2])
dp[pos][2]+=min(dp[x][0],dp[x][2])
dp[pos][2]+=k,dp[pos][0]+=s[pos]
k=min(k,dp[pos][0]-min(dp[pos][0],dp[pos][2]));
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
int dp[][];
struct node{
int u,v,nex;
}x[];
int s[];
int a[],cnt,n;
int head[];
void add(int u,int v)
{
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
int dfs(int pos,int fath)
{
int k=;
for(int i=head[pos];i!=-;i=x[i].nex)
{
int p=x[i].v;
if(p==fath) continue;
dfs(p,pos);
dp[pos][]+=min(min(dp[p][],dp[p][]),dp[p][]);
dp[pos][]+=min(dp[p][],dp[p][]);
dp[pos][]+=min(dp[p][],dp[p][]);
k=min(k,dp[p][]-min(dp[p][],dp[p][]));
}
dp[pos][]+=s[pos];
dp[pos][]+=k;
}
int main()
{
memset(head,-,sizeof(head));
n=read();
for(int i=;i<=n;i++)
{
int xx=read();
s[xx]=read();
int m=read();
for(int j=;j<=m;j++)
{
int p=read();
// cout<<xx<<" "<<p<<endl;
add(xx,p);
add(p,xx);
}
}
dfs(,);
cout<<min(dp[][],dp[][]);
}

加分二叉树[loj 10158]

/*
中序遍历
左子树——根——右子树
每次枚举根
进行记忆化dfs
将last存放最优根
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
int dp[][],s[],n,last[][];
int dfs(int l,int r)
{
// cout<<l<<" "<<r<<endl;
if(l==r) return s[l];
if(l>r) return ;
if(dp[l][r]!=-) return dp[l][r];
for(int i=l;i<=r;i++)
{
int p=dfs(l,i-)*dfs(i+,r)+s[i];
if(p>dp[l][r])
{
dp[l][r]=p;
last[l][r]=i;
}
}
return dp[l][r];
}
void sc(int l,int r)
{ if(l>r) return;
if(l==r)
{
cout<<l<<" ";
return;
}
cout<<last[l][r]<<" ";
sc(l,last[l][r]-);
sc(last[l][r]+,r);
return;
}
int main()
{
memset(dp,-,sizeof(dp));
n=read();
for(int i=;i<=n;i++) s[i]=read();
cout<<dfs(,n)<<endl;
// cout<<
sc(,n);
}

旅游规划[loj 10159]

/*
此题是找最长链上的所有店
dp1求子树上最长路径
dp2求子树上次长路径 两者相加便可以求出最长路径的长度 dp3记录除子树外的最长路径 */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
struct node{
int u,v,nex;
}x[];
int n,cnt,head[];
int book[],dp3[],maxn,dp1[],dp2[];
void add(int u,int v)
{
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
void dfs(int pos)
{
// cout<<pos<<endl;
for(int i=head[pos];i!=-;i=x[i].nex)
{
int p=x[i].v;
// cout<<p<<endl;
if(book[p]==)
{
book[p]=;
dfs(p);
if(dp1[p]+>=dp1[pos])
{
dp2[pos]=dp1[pos];
dp1[pos]=dp1[p]+;
}
else if(dp1[p]+>=dp2[pos])
dp2[pos]=dp1[p]+;
maxn=max(maxn,dp1[pos]+dp2[pos]);
}
}
return;
}
void dfs1(int pos,int fath)
{
int sum=;
for(int i=head[pos];i!=-;i=x[i].nex)
if(x[i].v!=fath&&dp1[pos]==dp1[x[i].v]+) sum++;
for(int i=head[pos];i!=-;i=x[i].nex)
{
if(x[i].v!=fath)
{
if(dp1[x[i].v]+!=dp1[pos]) dp3[x[i].v]=max(dp1[pos],dp3[pos])+;
else if(dp1[x[i].v]+==dp1[pos]&&sum>)dp3[x[i].v]=max(dp1[pos],dp3[pos])+;
else dp3[x[i].v]=max(dp2[pos],dp3[pos])+;
dfs1(x[i].v,pos);
}
}
}
int main()
{
memset(head,-,sizeof(head));
n=read();
// for(int i=0;i<n;i++) f[i]=i;
for(int i=;i<n;i++)
{
int u=read(),v=read();
add(u,v),add(v,u);
}
book[]=;
dfs();
// cout<<maxn<<" ";
memset(book,,sizeof(book));
dfs1(,-);
for(int i=;i<n;i++)
if(dp1[i]+max(dp2[i],dp3[i])==maxn) cout<<i<<endl;
return ;
}

周年纪念晚会[loj 10160]

/*
0不选1选
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
int a[],n;
struct node{
int u,v,nex;
}x[];
int cnt;
int head[],dp[][],t[];
void add(int u,int v)
{
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
void dfs(int pos)
{
// cout<<pos<<endl;
dp[pos][]=;
dp[pos][]=a[pos];
for(int i=head[pos];i!=-;i=x[i].nex)
{
int p=x[i].v;
dfs(p);
dp[pos][]+=max(,max(dp[p][],dp[p][]));
dp[pos][]+=max(,dp[p][]); }
}
int main()
{
memset(head,-,sizeof(head));
n=read();
memset(dp,0xcf,sizeof(dp));
for(int i=;i<=n;i++) a[i]=read();
for(int i=;i<n;i++)
{
int u=read(),v=read();
add(v,u);t[u]=;
}
int sry=;
while(t[sry]==) sry++;
dfs(sry);
cout<<max(dp[sry][],dp[sry][]);
}

叶子的颜色[loj 10161]

/*
dp[pos][0]表示pos涂黑色
1 表示涂白色
2 表示不涂 dp[pos][0]+=min(dp[x][0]-1,dp[x][1],dp[x][2])
1,2同理 -1是因为此点就不需要涂 预处理见代码
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
int m,n,c[];
struct node{
int u,v,nex;
}x[];
int head[],cnt;
void add(int u,int v)
{
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
int book[],dp[][];
void dfs(int pos)
{
if(pos>=&&pos<=m)
{
dp[pos][c[pos]]=;
dp[pos][-c[pos]]=dp[pos][]=<<-;
}
else{
dp[pos][]=dp[pos][]=;
}
for(int i=head[pos];i!=-;i=x[i].nex)
{
int t=x[i].v;
if(book[t]==)
{
book[t]=;
dfs(t);
dp[pos][]+=min(dp[t][]-,min(dp[t][],dp[t][]));
dp[pos][]+=min(dp[t][]-,min(dp[t][],dp[t][]));
dp[pos][]+=min(dp[t][],min(dp[t][],dp[t][]));
}
}
}
int main()
{
memset(head,-,sizeof(head));
n=read(),m=read();
for(int i=;i<=m;i++) c[i]=read();
for(int i=;i<n;i++)
{
int u=read(),v=read();
add(u,v),add(v,u);
}
book[n]=;
dfs(n);
cout<<min(dp[n][],min(dp[n][],dp[n][]));
}

骑士[loj 10162]

/*
断环为链,与没有上司的舞会接下来的十分相似
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
struct node{
long long u,v,nex;
}x[];
long long cnt;
long long head[],n,s[],vis[],root,book[],uu,vv;
void add(long long u,long long v)
{
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
} bool flag;
long long ans;
void dfs(long long pos,long long fa)
{
for(long long i=head[pos];i!=-;i=x[i].nex)
{
long long p=x[i].v;
if(fa!=p)
{
if(vis[p]==)
{
vis[p]=;
dfs(p,pos);
}
else{
flag=true;
uu=pos,vv=p;
}
}
}
}
long long dp[][];//0没用,1用
long long inf=<<-;
void dfs_dp(long long pos,long long fa)
{
// cout<<pos<<endl;
dp[pos][]=s[pos];
for(long long i=head[pos];i!=-;i=x[i].nex)
{
long long p=x[i].v;
if(p!=fa)
{
if(p==-inf) continue;
dfs_dp(p,pos);
dp[pos][]+=max(dp[p][],dp[p][]);
dp[pos][]+=dp[p][];
}
}
return;
}
void work(long long pos)
{
memset(dp,,sizeof(dp));
flag=false;
vis[pos]=;
dfs(pos,-);
// cout<<uu<<" "<<vv<<endl;
if(flag==false)
{
dfs_dp(pos,-);
ans+=max(dp[pos][],dp[pos][]);
}
else if(flag==true)
{
long long maxn=;
for(long long i=head[uu];i!=-;i=x[i].nex)
{
long long p=x[i].v;
if(p==vv)
{
x[i].v=-inf;
break;
}
}
for(long long i=head[vv];i!=-;i=x[i].nex)
{
long long p=x[i].v;
if(p==uu)
{
x[i].v=-inf;
break;
}
}
// cout<<uu<<" "<<vv<<endl;
dfs_dp(uu,-);
// return ;
long long x1=dp[uu][];
// cout<<x1<<endl;
memset(dp,,sizeof(dp));
dfs_dp(vv,-);
long long x2=dp[vv][];
// cout<<x2<<endl;
maxn=max(x1,x2);
ans+=maxn;
}
}
int main(void)
{
memset(head,-,sizeof(head));
n=read();
for(long long i=;i<=n;i++)
{
s[i]=read();
long long p=read();
add(i,p),add(p,i);
}
for(long long i=;i<=n;i++)
{
if(vis[i]==)
{
work(i);
// return 0;
}
}
cout<<ans;
}

YBT 5.2 树形动态规划的更多相关文章

  1. 蓝桥杯 ALGO-4 结点选择 (树形动态规划)

    问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值.如果一个点被选择了,那么在树上和它相邻的点都不能被选择.求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n . 接下来的 ...

  2. 树形动态规划(树状DP)小结

    树状动态规划定义 之所以这样命名树规,是因为树形DP的这一特殊性:没有环,dfs是不会重复,而且具有明显而又严格的层数关系.利用这一特性,我们可以很清晰地根据题目写出一个在树(型结构)上的记忆化搜索的 ...

  3. 【ACM/ICPC2013】树形动态规划专题

    前言:按照计划,昨天应该是完成树形DP7题和二分图.最大流基础专题,但是由于我智商实在拙计,一直在理解树形DP的思想,所以第二个专题只能顺延到今天了.但是昨天把树形DP弄了个5成懂我是很高兴的!下面我 ...

  4. 【树形动态规划】【CTSC1997】选课 解题报告

    CTSC1997-选课 描述 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修了这 ...

  5. 「洛谷2495」「BZOJ3052」「SDOI2001」消耗战【虚树+树形动态规划】

    题目大意 给你\(k\)个点,让这一些点和一号节点断开,删去某一些边,求最小的删去边权之和. 做题的心路历程 做了\(HG\)昨天的模拟赛,深深感觉到了窝的菜,所以为了\(A\)掉T1这一道毒瘤,窝就 ...

  6. Codeforces 1000G Two-Paths 树形动态规划 LCA

    原文链接https://www.cnblogs.com/zhouzhendong/p/9246484.html 题目传送门 - Codeforces 1000G Two-Paths 题意 给定一棵有 ...

  7. 树形动态规划(树形DP)入门问题—初探 & 训练

    树形DP入门 poj 2342 Anniversary party   先来个题入门一下~ 题意: 某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上 ...

  8. BZOJ1040 [ZJOI2008]骑士 基环树林(环套树) 树形动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题意概括 有n个人,每一个人有一个最恨的人. 并且,每一个人有一个权值. 一个人不可以和他最恨的人同时被选中. 现在请你求出在 ...

  9. Vijos1906 联合权值 NOIP2014Day1T2 树形动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - Vijos1906 题意概括 有一棵树,每一个节点都有一个权值w[i].下面说的x,y都是该树中的节点. 对于 ...

随机推荐

  1. mysql优化理解笔记(持续更新)

    主要包括存储引擎.索引.sql语句 一.存储引擎 目前最常见的是InnoDB和MyISAM两个存储引擎 (1)InnoDB:支持事务处理,提供行级锁.外键约束索引,行锁 (2)MyISAM:支持全文搜 ...

  2. 使用Iview Menu 导航菜单(非 template/render 模式)

    1.首先直接参照官网Demo例子,将代码拷贝进项目中运行, 直接报错: Cannot read property 'mode' of undefined. 然后查看官网介绍,有一行注意文字,好吧. 2 ...

  3. 【MySQL解惑笔记】Navicat 无法远程连接MySQL数据库

    安装好Navicat之后远程连接MySQL数据库出现以下报错截图: 出现以上截图怀疑是mysql用户权限不够: GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.1 ...

  4. I Hate It:线段树:单点修改+区间查询

    I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  5. solidity合约详解

    Solidity 是一个面向合约的高级语言,其语法类似于JavaScript .是运行在以太坊虚拟机中的代码.这里我们用的是remix编译环境.是一个在线的编译环境.地址为http://remix.e ...

  6. Centos6更新yum repo

    163开源镜像站是国内比较老的一个网站.很多人都在使用. step 1/3 备份原镜像文件: cd /etc/yum.repos.d mv CentOS-Base.repo CentOS-Base.r ...

  7. Cow Contest(最短路floyed传递闭包)

    Description N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming con ...

  8. Python学习之路3 - 字符串操作&字典

    本节内容: 常用的字符串处理. 格式化输出字符串. 字符串的替换. 字符串和二进制的相互转化. 字典的操作 字符串操作 常用的字符串处理 name = 'vector' print(name.capi ...

  9. Alpha-2

    前言 失心疯病源2 团队代码管理github 站立会议 队名:PMS 530雨勤(组长) 今天完成了那些任务 17:30~21:30 又测试了一些算法和代码,时间不能再拖下去了,要尽快进入代码阶段,决 ...

  10. 什么是RESTFUL协议?

    1,restful是Representational State Transfer的缩写,翻译过来是表现层状态转移.我的理解是去掉访问文件的格式,比如去掉文件为html的.html,而是采用路径的方式 ...