【树形dp】没有上司的舞会(C++)

描述

有个公司要举行一场晚会。
为了能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会邀请他的上司
(上司的上司,上司的上司的上司……都可以邀请)。
题目
每个参加晚会的人都能为晚会增添一些气氛,求一个邀请方案,使气氛值的和最大。

输入

第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, f [ x ] [ 0 ] f[x][0] 代表不选这个节点的最大值, f [ x ] [ 1 ] f[x][1] 代表选择这个节点的最大值
接着,我们再推导出状态转移方程,推出来是这样的 f [ x ] [ 0 ] = f [ x ] [ 0 ] m a x ( f [ i ] [ 1 ] , f [ i ] [ 0 ] ) f[x][0]=f[x][0]max(f[i][1],f[i][0]) f [ x ] [ 1 ] = f [ x ] [ 1 ] + f [ i ] [ 0 ] f[x][1]=f[x][1]+f[i][0]
(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,先看看模板题,没有丧尸的舞会。”

猜你喜欢

转载自blog.csdn.net/liuzich/article/details/107672918
今日推荐