看到了一样的题,直接把POJ上的替贴了进来,发现TLE了HDU上的测试数也太多了吧,分析了下POJ的代码,发现时间复杂度过高(有点暴力倾向),只要修改代码了。。。
题意:
某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知每个人的活跃指数和上司关系(当然不可能存在环),求邀请哪些人(多少人)来能使得晚会的总活跃指数最大。
思路:
任何一个点的取舍可以看作一种决策,那么状态就是在某个点取的时候或者不取的时候,以他为根的子树能有的最大活跃总值。分别可以用f[i,1]和f[i,0]表示第i个人来和不来直接记录在结构体中~
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<map>
using namespace std;
#define N 6001
struct node
{
int father;
int child;
int brother;
int attend;//参加了
int notattend;//没有参加
void init()
{
father=0;
child=0;
brother=0;
notattend=0;
}
} p[N];
void dfs(int start)
{
int child;
child=p[start].child;
while(child)
{
dfs(child);
p[start].attend+=p[child].notattend;
if(p[child].attend>p[child].notattend)
p[start].notattend+=p[child].attend;
else
p[start].notattend+=p[child].notattend;
child=p[child].brother;//兄弟结点
}
}
int main()
{
int n,root;
while(scanf("%d",&n)!=EOF)
{
for(int i=1; i<=n; i++)
{
p[i].init();
scanf("%d",&p[i].attend);
}
int a,b;
while(scanf("%d%d",&a,&b),a||b)
{
root=b;
p[a].father=b;
p[a].brother=p[b].child;
p[b].child=a;
}
while(p[root].father)//寻找父节点
root=p[root].father;
dfs(root);
printf("%d\n",p[root].attend>p[root].notattend?p[root].attend:p[root].notattend);
}
}