描述
有个公司要举行一场晚会。
为了能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会邀请他的上司
(上司的上司,上司的上司的上司……都可以邀请)。
题目
每个参加晚会的人都能为晚会增添一些气氛,求一个邀请方案,使气氛值的和最大。
输入
第1行一个整数N(1<=N<=6000)表示公司的人数。
接下来N行每行一个整数。第i行的数表示第i个人的气氛值x(-128<=x<=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
由于入门oj炸了,所以我现在在Mushroom OJ做题,这是我老师做的网站(据说是liao用脚打出来的,但是我发现这是抄过来的网站)
这个题是树形dp的模板题,思路是这样的:
定义一个二维数组g,用来存每个节点连接的节点
定义一个二维数组f,
代表不选这个节点的最大值,
代表选择这个节点的最大值
接着,我们再推导出状态转移方程,推出来是这样的
和
(i代表连接的节点之一)
于是我开心的交上了代码:
#include<bits/stdc++.h>
using namespace std;
int g[6010][6010],num[6010];
int n,x,y;
int f[6010][2];
int r[6010];
int ss[6010];
void dfs(int x) {
for(int j=1; j<=num[x]; j++) {
int i=g[x][j];
dfs(i);
f[x][0]+=max(f[i][1],f[i][0]);
f[x][1]+=f[i][0];
}
f[x][1]+=r[x];
}
int main() {
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&r[i]);
while(scanf("%d%d",&x,&y)==2,x!=0||y!=0) {
num[y]++;
g[y][num[y]]=x;
ss[x]=y;
}
for(int i=1; i<=n; i++)
if(ss[i]==0) {
dfs(i);
printf("%d\n",max(f[i][1],f[i][0]));
break;
}
return 0;
}
接着:
改改就行了!
代码:
#include<bits/stdc++.h>
using namespace std;
int g[6010][100001],num[6010];
int n,x,y;
int f[6010][2];
int r[6010];
int ss[6010];
void dfs(int x) {
for(int j=1; j<=num[x]; j++) {
int i=g[x][j];
dfs(i);
f[x][0]+=max(f[i][1],f[i][0]);
f[x][1]+=f[i][0];
}
f[x][1]+=r[x];
}
int main() {
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&r[i]);
while(scanf("%d%d",&x,&y)==2,x!=0||y!=0) {
num[y]++;
g[y][num[y]]=x;
ss[x]=y;
}
for(int i=1; i<=n; i++)
if(ss[i]==0) {
dfs(i);
printf("%d\n",max(f[i][1],f[i][0]));
break;
}
return 0;
}
结果:
???
很神奇!
接着,我又改了改:
#include<bits/stdc++.h>
using namespace std;
vector<int> g[6010];
int n,x,y;
int f[6010][2];
int r[6010];
int ss[6010];
void dfs(int x) {
for(int j=0; j<g[x].size(); j++) {
int i=g[x][j];
dfs(i);
f[x][0]+=max(f[i][1],f[i][0]);
f[x][1]+=f[i][0];
}
f[x][1]+=r[x];
}
int main() {
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&r[i]);
while(scanf("%d%d",&x,&y)==2,x!=0||y!=0) {
g[y].push_back(x);
ss[x]=y;
}
for(int i=1; i<=n; i++)
if(ss[i]==0) {
dfs(i);
printf("%d\n",max(f[i][1],f[i][0]));
break;
}
return 0;
}
终于AC了!
关于这道题的一个趣事
老师给我们讲这个题时,发音不准,说成了这样:“今天,我们来讲讲树形dp,先看看模板题,没有丧尸的舞会。”