Time Limit: 1 second
Memory Limit: 128 MB
【问题描述】
某大学有N个职员,编号为1~N。他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri,但是呢,如果某个职员的上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。【输入格式】
第一行一个整数N。(1<=N<=6000) 接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127) 接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。 最后一行输入0 0
【输出格式】
输出最大的快乐指数。
【数据规模】
Sample Input1
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
Sample Output1
5
【题解】
题目的意思是说某个节点如果它的"直接"上司来了,它就不能来。
设一个数组f[i]表示i这个节点所在的人是否参加舞会所能达到的最大快乐度。其中f[i]数组有两维,f[i].fang表示i这个节点的人参加舞会,f[i].bufang表示i这个节点的人不参加舞会。
如果i这个节点的人参加舞会。即f[i].fang,则对于i节点来说。它的儿子节点们就只能不放(不参加)。
然后对于f[i].bufang表示i这个人不参加舞会所能达到的最大快乐度。然后对于其儿子节点们,对应的状态就可以是参加或不参加都行。
这样进行递归。
void dfs (int now)
{
for (now的所有儿子节点son)
for (now的所有儿子节点son)
{
f[son].fang = r[son];
dfs(son);
f[now].fang = max{f[now].fang,f[now].fang+f[son].bufang};
f[now].bufang = max{f[now].bufang,f[now].bufang+max{f[son].bufang,f[son].fang}};
}
}
}
从0号节点(不存在)开始。
然后如果某个节点它没有父亲(根节点),那么默认就是0啦。
即可以方便找到根节点,不用特判。
最后输出f[0].bufang.(肯定不放是最优的。如果放了的话根节点咋办????)
【代码】
#include <cstdio> struct data2 //存放的状态 { int fang, bufang; }; int n, r[6001], fa[6001] = { 0 }; data2 f[6001] = { 0 }; int max(int a, int b)//返回a和b中的较大值。 { return a>b ? a : b; } void dfs(int now)//当前到了now这个节点。接下来要寻找到它的儿子们。 { for (int son = 1; son <= n; son++) if (fa[son] == now)//如果它的爸爸是now。 { f[son].fang = r[son];//表示其先等于快乐值(放) //你完全可以再写上一句f[son].bufang= 0 dfs(son);//递归儿子 f[now].bufang = max(f[now].bufang, max(f[now].bufang + f[son].fang, f[now].bufang + f[son].bufang));//如果不放, //则儿子有什么状态都能递增上去,取最优值即可 f[now].fang = max(f[now].fang, f[now].fang + f[son].bufang); //如果放了的话,儿子当中就只能取不放的状态了。同样取最优值。 } } int main() { // freopen("E:\rush.txt","r",stdin); scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &r[i]); int x0, y0; scanf("%d%d", &x0, &y0);//输入数据 while (x0 != 0) { fa[x0] = y0;//记录谁的爸爸是谁。。。 scanf("%d%d", &x0, &y0); } dfs(0);//从0开始递归 printf("%d ", f[0].bufang);//最后输出0不放的结果.(最优值) return 0; }