ICPC亚洲区域赛(南京) M.Monster Hunter(树形dp)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ICPC亚洲区域赛(南京) M.Monster Hunter(树形dp)相关的知识,希望对你有一定的参考价值。
转化题意,把每个点的权值放在自己和父亲上计算
①.树形背包解法
那么其实这是一个树型 d p dp dp的过程
定义 f [ i ] [ j ] [ 0 / 1 ] f[i][j][0/1] f[i][j][0/1]表示子树中 j j j个点没有被删去(也就是选择了 j j j个点)的最小权值和
那么初始化 f [ u ] [ 0 ] [ 0 ] = 0 , f [ u ] [ 1 ] [ 1 ] = w u f[u][0][0]=0,f[u][1][1]=w_u f[u][0][0]=0,f[u][1][1]=wu
这样刚好和背包的定义吻合
但是这样 d p dp dp数组的定义刚好和题意相反,所以需要倒序输出。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 2009;
const long long inf = 1ll*1e18;
int t,n,w[maxn];
long long f[maxn][maxn][2];
vector<int>vec[maxn];
int siz[maxn];
void dfs(int u)
{
//f[i][j][0/1]表示i子树内花费j次魔力的最小代价,此时i是否被删掉
siz[u] = 1;
f[u][0][0] = 0; f[u][1][1] = w[u];
for( auto v:vec[u] )
{
dfs( v );
for(int j=siz[u];j>=0;j--)//u子树内选多少物品
for(int q=siz[v];q>=0;q--)//v子树内选多少个物品
{
f[u][j+q][0] = min( f[u][j+q][0],f[u][j][0]+min( f[v][q][0],f[v][q][1] ) );
f[u][j+q][1] = min( f[u][j+q][1],f[u][j][1]+min( f[v][q][0],f[v][q][1]+w[v] ) );
}
siz[u] += siz[v];
}
}
signed main()
{
cin >> t;
while( t-- )
{
cin >> n;
for(int i=2;i<=n;i++)
{
int x; cin >> x;
vec[x].push_back( i );
}
for(int i=1;i<=n;i++) cin >> w[i];
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
f[i][j][0] = f[i][j][1] = inf;
dfs(1);
for(int i=n;i>=0;i--)
cout << min( f[1][i][0],f[1][i][1] ) << " ",vec[i].clear();
cout << endl;
}
}
②.
定义 f [ i ] [ j ] [ 0 / 1 ] f[i][j][0/1] f[i][j][0/1]表示子树中 j j j个点被删去时(0/1自己没被删去/被删去)的最小权值和
那么初始化 f [ u ] [ 0 ] [ 0 ] = w [ u ] , f [ u ] [ 1 ] [ 1 ] = 0 f[u][0][0] = w[u],f[u][1][1] = 0 f[u][0][0]=w[u],f[u][1][1]=0
转移的话和上面差不多,但是需要额外开数组来辅助转移
因为这里面有个滚动的过程,也就是需要把前 x x x个子树和当前子树合并起来
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 2009;
const long long inf = 1ll*1e18;
int t,n,w[maxn];
long long f[maxn][maxn][2],temp[maxn][2];
vector<int>vec[maxn];
int siz[maxn];
void dfs(int u)
{
//f[i][j][0/1]表示i子树内花费j次魔力的最小代价,此时i是否被删掉
siz[u] = 1;
f[u][0][0] = w[u]; f[u][1][1] = 0;
for( auto v:vec[u] )
{
dfs( v );
memset( temp,0x3f,sizeof temp );
for(int i=siz[u];i>=0;i--)
for(int j=siz[v];j>=0;j--)
{
int v1 = min( f[u][i][0]+f[v][j][0]+w[v],f[u][i][0]+f[v][j][1] );
int v2 = min( f[u][i][1]+f[v][j][0],f[u][i][1]+f[v][j][1] );
temp[i+j][0] = min( temp[i+j][0],v1 );
temp[i+j][1] = min( temp[i+j][1],v2 );
}
siz[u] += siz[v];
for(int i=0;i<=siz[u];i++)
f[u][i][0] = temp[i][0],f[u][i][1] = temp[i][1];
}
}
signed main()
{
cin >> t;
while( t-- )
{
cin >> n;
for(int i=2;i<=n;i++)
{
int x; cin >> x;
vec[x].push_back( i );
}
for(int i=1;i<=n;i++) cin >> w[i];
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
f[i][j][0] = f[i][j][1] = inf;
dfs(1);
for(int i=0;i<=n;i++)
cout << min( f[1][i][0],f[1][i][1] ) << " ",vec[i].clear();
cout << endl;
}
}
以上是关于ICPC亚洲区域赛(南京) M.Monster Hunter(树形dp)的主要内容,如果未能解决你的问题,请参考以下文章
第 46 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京),签到题5题
第 46 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京),签到题5题
第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京),签到题4题
第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京),签到题4题