题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1520
方法: 领导选择出现,则其直接下属不能出现,领导选择不出现,则其直接下属可出现可不出现,设F(P,0)为一个员工不出现能得的最大值,F(P,1)为一个员工要出现能得的最大值
{
sum({F(S,0)|S是p的直接下属})+p的有趣度;P为非叶子
F(P,1)=
p的有趣度;P为叶子
},
{
sum({ min(F(S,1),F(S,0)) |S是p的直接下属 });P为非叶子
F(P,0)=
0;P为叶子
}
原来问题的解是min(F(root,1),F(root,0)).
注意输入不一定是树结构,有可能是森林,所以要把所有的树都DP一次,把结果累加起来。
代码:
#include <iostream> #include <queue> #include<algorithm> using namespace std; int n,m; struct Arc { int vetex; Arc* nextArc; }; struct Node { int x; int inDegree; Arc* firstArc; int value; int in; int notIn; }; Node nodes[6001]; int myMax(int x,int y) { return x>y ? x:y; } void DFSDP(int root) { Arc* arc = nodes[root].firstArc; int sonCount=0,v; while(arc!=NULL) { v=arc->vetex; DFSDP(v); nodes[root].in+=nodes[v].notIn; nodes[root].notIn+=myMax(nodes[v].notIn,nodes[v].in); arc=arc->nextArc; sonCount++; } if(sonCount==0) { nodes[root].in=nodes[root].value; nodes[root].notIn=0; } } void createArc(int s,int e) { Arc* arc = (Arc*)malloc(sizeof(Arc)); arc->vetex=e; if(nodes[s].firstArc==NULL) arc->nextArc=NULL; else arc->nextArc=nodes[s].firstArc; nodes[s].firstArc = arc; } void main() { while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++) { scanf("%d",&nodes[i].value); nodes[i].firstArc=NULL; nodes[i].notIn=nodes[i].inDegree=0; nodes[i].in=nodes[i].value; } int emp,boss; while(scanf("%d %d",&emp,&boss) && !(emp==0 && boss==0)) { nodes[boss].x = boss; nodes[emp].x = emp; createArc(boss,emp); nodes[emp].inDegree++; } int re=0; for(int i =1;i<=n;i++) { if(nodes[i].inDegree==0) { DFSDP(i); re+=myMax(nodes[i].in,nodes[i].notIn); } } cout<<re<<endl; } }
感想:模板题