ICPC亚洲区域赛(南京) M.Monster Hunter(树形dp)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ICPC亚洲区域赛(南京) M.Monster Hunter(树形dp)相关的知识,希望对你有一定的参考价值。

LINK

转化题意,把每个点的权值放在自己和父亲上计算

①.树形背包解法

那么其实这是一个树型 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题

第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京)签到题F Fireworks

第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京)签到题F Fireworks