【Usaco2006Mar】Milk Team Select产奶比赛

【思路分析】

比赛的时候想到了用我确实也想到了树形DP,但是状态没有确定对,连样例都没有过
PS:这是第二道发现还可以用状态作为答案最后输出的题目

正解:树形DP(背包)

按照读进来的数据,我们先建一棵树
像这样(这里用vector存图)

	for(int i=1;i<=n;++i){
	int x=read(),y=read();
	a[i]=x;	 v[y].push_back(i);//从父节点建一条边连向子节点
}
然后就是DP的过程
(本人见到的树形DP题目比较少,但是做到过相关的题目似乎都是想这样子的)

void dfs(int x){
***********************//这里写初始化,或者边界判断
for(int i=0;i<v[x].size();i++){
int nxt=v[x][i];
dfs(nxt);//先处理它的子树
************************//这里写转移方程
}
***************************//这里进行后续操作
}

确定了是树形dp之后,我们来想一下转移方程

f[i][j][1]表示i节点分配j个亲缘关系取后最多的产奶量

f[i][j][0]表示该节点分配j个亲缘关系不取后最多的产奶量

然后像背包一样

我们给第i个子树分配j个关系

可以得出方程

方程:

(未加初始化与后续处理)
f[x][j][0]=max(f[x][j][0],f[x][j-k][0]+max(f[nxt][k][0],f[nxt][k][1])),
f[x][j][1]=max(f[x][j][1],f[x][j-k][1]+max(k==0?-0x3f3f3f3f:f[nxt][k-1][1],f[nxt][k][0]));

AC代码大概是这样的:

代码:

#include<cstdio>
#include<cmath>
#include<cctype>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
using namespace std;
inline int read()
{
	char chr=getchar();
	int f=1,ans=0;
	while(!isdigit(chr)) {if(chr=='-') f=-1;chr=getchar();}
	while(isdigit(chr))  {ans=(ans<<1)+(ans<<3)+chr-'0';chr=getchar();}
	return ans*f;
}

inline void kai()
{
	freopen("d.in","r",stdin);
	freopen("d.out","w",stdout);
}
int n,m,a[505];
vector<int> v[505];
int f[505][505][2];
void dfs(int x){
	for(int i=1;i<=n;i++) f[x][i][0]=f[x][i][1]=-0x3f3f3f3f;//预处理
	for(int i=0;i<v[x].size();i++){
		int nxt=v[x][i];
		dfs(nxt);//遍历子树
		for(int j=n;j>=0;j--)
			for(int k=0;k<=j;k++)
			f[x][j][0]=max(f[x][j][0],f[x][j-k][0]+max(f[nxt][k][0],f[nxt][k][1])),
			f[x][j][1]=max(f[x][j][1],f[x][j-k][1]+max(k==0?-0x3f3f3f3f:f[nxt][k-1][1],f[nxt][k][0]));//方程
	}
	for(int i=0;i<=n;i++) f[x][i][1]+=a[x];//后续处理
}
int ans=0,maxn=0;
int main(){
	n=read();
	m=read();
	for(int i=1;i<=n;++i){
		int x=read(),y=read();
		a[i]=x;	 v[y].push_back(i);//建树
	}
	dfs(0);//建一个“超级节点”(所有没有祖先的根节点都连到了0上)
	int i;
	for(i=n;i;i--) if(f[0][i][0]>=m) break;//用状态来做答案,找到第一个产奶量最多的亲缘关系(倒续找,所以最先找到的就是最大的)
	cout<<i;
	return 0;
}
posted @ 2018-08-20 20:24  zheng_liwen  阅读(139)  评论(0编辑  收藏  举报
/*去广告*/