您的位置:首页 > 其它

Codevs1380 没有上司的舞会

2015-09-01 19:47 281 查看
题目大意: Ural大学有N个职员,编号为1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。要你求出舞会可以组织出的最大快乐指数。

思路:显然,这是一个树形DP。因为一个根节点选不选会产生不同的情况,所以要开一个二维数组进行记录。记f[i][0]表示以i为根的子树在选择i的情况下能达到的最大快乐值,f[i][1]表示以i为根的子树在不选择i的情况下能达到的最大快乐值,显然状态转移方程有f[i,0]+=max(f[son[i],0],f[son[i],1],f[i,1]=∑f[son[i],0]+value[i]。最后,ans=max(f[root,1],f[root,0])。但根并没有给出,所以需要处理找根。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=6005;
int n,c[maxn],f[maxn][2],root;
vector<int> son[maxn];
bool rot[maxn];

void init()
{
     scanf("%d",&n);
     memset(rot,1,sizeof(rot));
     for (int i=1;i<=n;++i)
     {
         int ci;
         scanf("%d",&ci);
         c[i]=ci;
     }
     int l,k;
     while (scanf("%d%d",&l,&k)==2)
     {
           if (l==0 && k==0)
             break;
           son[k].push_back(l);
           rot[l]=0;
     }
     memset(f,0,sizeof(f));
}

void getroot()
{
     for (int i=1;i<=n;++i)
     {
         if (rot[i])
         {
              root=i;
              return;
         }
     }
}

void solve(int root)
{
     if (son[root].empty())
     {
          f[root][1]=c[root];
          f[root][0]=0;
          return;
     }
     if (f[root][0]!=0 || f[root][1]!=0)
       return;
     vector<int>::iterator it;
     for (it=son[root].begin();it!=son[root].end();++it)
     {
         solve((*it));
     }
     for (it=son[root].begin();it!=son[root].end();++it)
       f[root][0]+=max(f[(*it)][1],f[(*it)][0]);
     for (it=son[root].begin();it!=son[root].end();++it)
       f[root][1]+=f[(*it)][0];
     f[root][1]+=c[root];
}

int main()
{
    init();
    getroot();
    solve(root);
    printf("%d",max(f[root][0],f[root][1]));
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: