没有上司的舞会--树形DP

没有上司的舞会
 
题目描述 
      Ural大学有N个职员,编号为1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。
输入描述 
第一行一个整数N。(1<=N<=6000)
接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)
接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。
最后一行输入0,0。
输出描述 

输出最大的快乐指数。

样例输入 

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0

样例输出 

5

#include<cstdio>
int n,l,k,ans,jo[6005],re[6005];
struct ty
{
 int data,fa,son,bro;
 
} t[6005];
int max(int a,int b)
{
 return a>b?a:b;
}
void find(int x,int y)//建树; 
{
 if(t[x].bro==0) t[x].bro=y;
 else find(t[x].bro,y);
}
int zhao(int x)//找根 
{
 if (t[x].fa==0) return x;
 else zhao(t[x].fa);
}
void dp(int x)
{
 if(!t[x].son&&!t[x].bro) {jo[x]=t[x].data;re[x]=0;}//是叶子节点的话,参加不参加。。 
 if(t[x].bro!=0) dp(t[x].bro);
 if(t[x].son!=0) dp(t[x].son);
 jo[t[x].fa]+=re[x];           //上司参加,直系下属不能参加; 
 re[t[x].fa]+=max(jo[x],re[x]);//上司不参加,直系下属参不参加无所谓,找max 
}
int main()
{
 scanf("%d",&n);
 for(int i=1;i<=n;i++) 
    {scanf("%d",&t[i].data);jo[i]=t[i].data;}//读入数据,顺便把i参加的快乐值加到jo[i] 
 scanf("%d%d",&l,&k);
 while(l!=0&&k!=0){//用的是兄弟孩子表示法 ; 
  t[l].fa=k;
  if(t[k].son==0) t[k].son=l;
  else find(t[k].son,l);
  scanf("%d%d",&l,&k);
 }
 k=zhao(n);//找到根节点; 
 dp(k);
 ans=max(jo[k],re[k]);//校长参不参加的最大值; 
 printf("%d",ans);
 return 0;
}
View Code

//人生第一次打树形DP,激动啊。。。。

原文地址:https://www.cnblogs.com/qingang/p/5178553.html