题目描述
Ural周立大学的校长正在筹备学校的80周年纪念聚会。由于学校的职员有不同的职务级别,可以构成一棵以校长为根的人事关系树。每个职员都有一个唯一的整数编号(范围在1到N之间),并且对应一个参加聚会所获得的欢乐度。为了使每个参加聚会者都感到欢乐,校长想设法使每个职员和他(她)的直接上司不会同时参加聚会。
你的任务是设计一份参加聚会者的名单,使总的欢乐度最高。
输入
输入的第一行是一个整数N,1<= N <= 6000
以下的N行是对应的N个职员的欢乐度(欢乐度是一个从-128到127之间的整数)
接着是学校的人事关系树,树的每一行格式如下:
< 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<iostream>
#include<queue>
#define MAXN 6005
using namespace std;
int n,h[MAXN],vis[MAXN],dp[MAXN][2];
vector<int> g[MAXN];
void dfs(int x)
{
dp[x][0]=0;
dp[x][1]=h[x];
for(int i=0;i<g[x].size();++i)
{
int v=g[x][i];
dfs(v);
dp[x][0]+=max(dp[v][1],dp[v][0]);
dp[x][1]+=dp[v][0];
}
}
int main()
{
int x,y,m,sum=0;
cin>>n;
for(int i=1;i<=n;i++)
cin>>h[i];
while(cin>>x>>y)
{
if(x==0&&y==0)
break;
g[y].push_back(x);//记录该上司的职员
vis[x]=1;
}
for(int i=1;i<=n;i++)
if(!vis[i])
{
m=i;
dfs(m);//从根节点开始dfs
sum+=max(dp[m][1],dp[m][0]);
}
cout<<sum<<endl;
return 0;
}