树形动态规划的基本写法

典型例题有三道:

没有上司的舞会

选课

景点中心

我们可以把动态规划的状态和转移描述成DAG

对于有根树来说,如果我们规定边的方向由父节点指向叶子节点

或者是由叶子节点指向父节点(奇葩)

那么它也是一个DAG

如果状态和转移都发生在特殊的DAG,树上

叫做树形动态规划

在树规中,父节点的值通过所有子节点计算完毕之后得出

这里上晚会

1A还是很舒服的,毕竟以前敲得很熟了

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn=6005;
 5 const int maxm=6005;
 6 int n;
 7 int r[maxn],vis[maxn],f[maxn][5];
 8 int cnt;
 9 int g[maxn];
10 struct Edge{int t,next;}e[maxm];
11 void addedge(int u,int v)
12 {
13     cnt++;
14     e[cnt].t=v;
15     e[cnt].next=g[u];
16     g[u]=cnt;
17 }
18 void dfs(int id)
19 {
20     f[id][1]=r[id];
21     if(g[id]==0) return;
22     //如果这是一个叶子,就到头了,我可是先赋值了给爹爹们用的哦 
23     for(int tmp=g[id];tmp;tmp=e[tmp].next)
24     {
25         dfs(e[tmp].t);
26         f[id][1]+=f[e[tmp].t][0];
27         //选id则id的所有儿子全部GG
28         if(f[e[tmp].t][0]>f[e[tmp].t][1])  //如果不选id,要看儿子们是选好还是不选好
29             f[id][0]+=f[e[tmp].t][0];
30         else f[id][0]+=f[e[tmp].t][1]; 
31     } 
32 }
33 int main()
34 {
35     int x,y;
36     scanf("%d",&n);
37     for(int i=1;i<=n;i++) scanf("%d",&r[i]);
38     for(int i=1;i<n;i++)
39     {
40         scanf("%d%d",&x,&y);
41         addedge(y,x);  //由BOSS指向员工这样遍历起来好处理 
42         vis[x]=1;  //标记这个不是根,只有BOSS上面没人 
43     }
44     for(int i=1;i<=n;i++)
45         if(!vis[i])
46         {
47             dfs(i);
48             printf("%d",max(f[i][0],f[i][1]));
49             break;
50         }
51     return 0;
52 }

猜你喜欢

转载自www.cnblogs.com/aininot260/p/9465256.html
今日推荐