7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
5
链接:点击打开链接
// 题意:一棵树每个节点有一个权值,保证父亲节点与孩子节点不能同时出现,求出现的节点最大权值。
// 基础树形dp。
#include <iostream>
using namespace std ;
struct Tree //用孩子兄弟表示法存储
{
int father ;
int child ;
int brother ;
int with_max; //表示选择该节点的子树所得的最大值
int without_max; //表示不选该节点的子树所得的最大值
int MAX() //现在再看这些写法,感觉很熟悉了。
{
return with_max>=without_max?with_max:without_max;
}
void init()
{
father=child=brother=without_max=0 ;
}
}tree[6001] ;
void dfs(int id)
{
int child;
child=tree[id].child;
while(child)
{
dfs(child);
tree[id].with_max+=tree[child].without_max; //dp---有父亲一定不能有儿子
tree[id].without_max+=tree[child].MAX(); //这里的tree[child].MAX()不能写成tree[child].with_max,因为没父亲儿子可有可无;
child=tree[child].brother;
}
}
int main()
{
int n,i;
while(~scanf("%d",&n))
{
for(i=1;i<=n;i++)
{
scanf("%d",&tree[i].with_max);
tree[i].init();
}
int a,b;
while(scanf("%d%d",&a,&b),a||b) //构造孩子兄弟树----很巧妙,注意方法,
{ //与书上讲的孩子兄弟树的存储方法不同不同
tree[a].father=b;
tree[a].brother=tree[b].child;
tree[b].child=a;
}
for(i=1;i<=n;i++)
if(!tree[i].father) //题目中说的是一个学校的组织,应该不会出现单独的部门吧,
{ //所以只会出现一棵树,即只有一根
dfs(i) ;
printf("%d\n",tree[i].MAX());
break ;
}
}
return 0 ;
}
code 2:
题意:
某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知每个人的活跃指数和上司关系(当然不可能存在环),求邀请哪些人(多少人)来能使得晚会的总活跃指数最大。
思路:
任何一个点的取舍可以看作一种决策,那么状态就是在某个点取的时候或者不取的时候,以他为根的子树能有的最大活跃总值。分别可以用f[i,1]和f[i,0]表示第i个人来和不来。
当i来的时候,dp[i][1] += dp[j][0];//j为i的下属
当i不来的时候,dp[i][0] +=max(dp[j][1],dp[j][0]);//j为i的下属
以下代码参考:http://hi.baidu.com/saintlleo/blog/item/0606b3feb7026ad3b48f3111.html
//AC CODE: