典型例题有三道:
没有上司的舞会
选课
景点中心
我们可以把动态规划的状态和转移描述成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 }