P1352 没有上司的舞会

题目描述

某大学有N个职员,编号为1~N。他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri,但是呢,如果某个职员的上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。

输入输出格式

输入格式:

第一行一个整数N。(1<=N<=6000)

接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)

接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。

最后一行输入0 0

输出格式:

输出最大的快乐指数。

输入输出样例

输入样例#1: 复制

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
输出样例#1: 复制

5

树形DP——DFS版

#include<bits/stdc++.h>

#define N 6005
using namespace std; int n,r[N],dp[N][],tot,head[N];
struct node{
int to,next;
}e[N]; bool v[N];
void add(int u,int v){
e[++tot].to=v,e[tot].next=head[u],head[u]=tot;
}
//dp[i][0]表示i点不被选择时最大值
//dp[i][1]表示i点被选择时的最大值
void tredp(int u){
dp[u][]=,dp[u][]=r[u];
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
tredp(v);
dp[u][]+=max(dp[v][],dp[v][]);
dp[u][]+=dp[v][];
}
} int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&r[i]);
for(int a,b,i=;i<n;i++){
scanf("%d%d",&a,&b);
add(b,a);v[a]=;
}
int root;
for(int i=;i<=n;i++) if(!v[i]) root=i;
tredp(root);
printf("%d\n",max(dp[root][],dp[root][]));
return ;
}

树形DP——倒序队列或栈

#include<bits/stdc++.h>

#define N 6005
using namespace std; int n,r[N],dp[N][],tot,head[N];
struct node{
int to,next;
}e[N]; bool v[N];
void add(int u,int v){
e[++tot].to=v,e[tot].next=head[u],head[u]=tot;
}
//dp[i][0]表示i点不被选择时最大值
//dp[i][1]表示i点被选择时的最大值
queue<int>Q;
stack<int>q;
bool vis[N];
void bfs(int root){
Q.push(root);
while(!Q.empty()){
int u=Q.front();Q.pop();q.push(u);
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(!vis[v]){
vis[v]=;
Q.push(v);
}
}
}
while(!q.empty()){
int u=q.top();q.pop();
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
dp[u][]+=max(dp[v][],dp[v][]);
dp[u][]+=dp[v][];
}dp[u][]+=r[u];
}
} int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&r[i]);
for(int a,b,i=;i<n;i++){
scanf("%d%d",&a,&b);
add(b,a);v[a]=;
}
int root;
for(int i=;i<=n;i++) if(!v[i]) root=i;
bfs(root);
printf("%d\n",max(dp[root][],dp[root][]));
return ;
}

拓扑排序——反向建边

#include<bits/stdc++.h>

#define N 6005
using namespace std; int n,r[N],dp[N][],tot,head[N],rd[N];
struct node{
int to,next;
}e[N]; void add(int u,int v){
e[++tot].to=v,e[tot].next=head[u],head[u]=tot;
}
//dp[i][0]表示i点不被选择时最大值
//dp[i][1]表示i点被选择时的最大值
bool v[N];
queue<int>Q;
void topo(){
for(int i=;i<=n;i++) if(!rd[i]) Q.push(i);
while(!Q.empty()){
int u=Q.front();Q.pop();dp[u][]+=r[u];
for(int i=head[u];i;i=e[i].next){
int V=e[i].to;
rd[V]--;
if(!rd[V]) Q.push(V);
dp[V][]+=max(dp[u][],dp[u][]);
dp[V][]+=dp[u][];
}
}
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&r[i]);
for(int a,b,i=;i<n;i++){
scanf("%d%d",&a,&b);
add(a,b);rd[b]++;v[a]=;
}
int root;
for(int i=;i<=n;i++) if(!v[i]) root=i;
topo();
printf("%d\n",max(dp[root][],dp[root][]));
return ;
}

最新文章

  1. Python环境配置安装
  2. iOS开发之Runtime机制深入解析
  3. ajax中使用post传值数组array
  4. Install CodeBlocks in CentOS 7
  5. ETHREAD APC 《寒江独钓》内核学习笔记(4)
  6. J2EE如何生成验证码图片和点击刷新验证码
  7. 【QT】视频播放+文件选择
  8. HDU 3966 Aragorn&#39;s Story (树链点权剖分,成段修改单点查询)
  9. 全局唯一ID的生成方式
  10. CodeForces 676D Theseus and labyrinth
  11. 开源社交系统ThinkSNS+ 0.7.3研发周报
  12. HTML中直接写js 函数
  13. java模式—装饰者模式
  14. sqlalchemy(一)常用连接参数及包
  15. centos 7.0 lnmp成功安装过程
  16. 通过SSH克隆远程仓库(GitLab)到本地
  17. 修改hadoop FileUtil.java,解决权限检查的问题
  18. Python学习笔记(四):字符串的学习
  19. js判断触摸方向
  20. MVC Controller传值到View的几种方式总结

热门文章

  1. 七、备忘录模式Memento(行为型模式)
  2. 西门子TCP/UDPport
  3. Android自定义用户控件简单范例(二)
  4. ubuntu rdesktop 全屏切换快捷键
  5. jquery 数组添加不重复数据
  6. ios-UI1
  7. 插入排序(1)——直接插入排序(insert sort)
  8. 自然常数 e 的理解与应用
  9. Secure CRT中解决vim高亮设置的方法
  10. PCB MS SQL 标量函数(CLR) 实现Socket发送消息