没错,我终于来更新树形dp了,当然也有一部分原因是因为上期的树形dp<1>灰常成功。
废话不多说,我们今天来看树形dp(废话)。至于树上背包呢,我就留到树形dp<3>吧。
首先,我看到了一篇树形dp的博客,还不错,给大家分享一下吧。
例题1:没有上司的舞会
这题可以说是一道比较经典的题目了。我们让表示以i为根的最优解。接下来就有了两种情况:①上司不参加舞会,下属参加,此时;②上次参加舞会,下属不参加,此时。然后用dfs递归实现就行了。
#include <bits/stdc++.h>
using namespace std;
struct edge{
int v;
int nxt;
}e[maxn];
int n,cnt,ans;
int head[maxn],dp[maxn][2];
bool ok[maxn],vis[maxn];
void add_edge(int u,int v){
e[++cnt].v=v;
e[cnt].nxt=head[u];
head[u]=cnt;
}
void dfs(int u){
vis[u]=true;
for(int i=head[u];i;i=e[i].nxt){//枚举该结点的每个子结点
if(vis[e[i].v])
continue;
dfs(e[i].v);
dp[u][1]+=dp[e[i].v][0];
dp[u][0]+=max(dp[e[i].v][0],dp[e[i].v][1]); // 转移方程
}
return;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>dp[i][1];
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
ok[u]=true;
add_edge(v,u);
}
for(int i=1;i<=n;i++){
if(!ok[i]){//从根结点开始DFS
dfs(i);
cout<<max(dp[i][1],dp[i][0])<<endl;
return 0;
}
}
}
参考文献:OI-Wiki
别走啊,还没完呢。
例题2:FAR-FarmCraft
建议各位看英文。
首先,我们令表示以i为根节点的子树中(包括节点i)的所有人安装好游戏所需要的时间;令表示兜一圈的时间。
注意:可能小于
所以我们分别看一下。
① :如果管理员回到了起点那些人还没有装完,那么就需要等待 f[i]−g[i]的时间所有人才能安装好。在等待的这段时间我们可以去下一家,以减少所需的总时间。这里我们贪心,让需要等待时间最久的作为第一个访问的节点,这样可以管理员在他的安装时间内将电脑送给其他人。② :随机访问即可,虽然我还是排了序。
结论(安装到第i个点):,其中j为比i先遍历到的同一层的节点。But Why?
表示遍历完所有j的子树的节点,每次都回到根节点(所以要+2);是因为root->i的哪一步;是i的子树的装好游戏的时间。
答案取max即可(为)。
#include <bits/stdc++.h>
using namespace std;
struct edge{
int to;
int nxt;
}e[maxn<<1];
int head[maxn],c[maxn],dp[maxn],t[maxn];
int n,cnt;
bool cmp(int x,int y){
return (dp[x]-t[x])>(dp[y]-t[y]);
}
void add_edge(int u,int v){
cnt++;
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt;
}
void dfs(int u,int fa){
vector<int> wait;
for(int i=head[u];i;i=e[i].nxt){
int to=e[i].to;
if(to==fa)
continue;
dfs(to,u);
wait.push_back(to);
}
sort(wait.begin(),wait.end(),cmp);
for(int i=0;i<wait.size();i++){
dp[u]=max(dp[u],t[u]+1+dp[wait[i]]);
t[u]+=t[wait[i]]+2;
}
if(c[u]>t[u] && u!=1)
dp[u]=max(dp[u],c[u]);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>c[i];
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
add_edge(u,v);
add_edge(v,u);
}
dfs(1,0);
cout<<max(dp[1],t[1]+c[1])<<endl;
return 0;
}
Ok,以上就是本期的全部内容了。我们树形dp<3>——树上背包再见!
温馨提示:本期的代码均有问题,请不要无脑Ctrl C+Ctrl V,看懂了自己写一遍.