树型dp(2019/1/19学习笔记)
就是做了一天简单的题有点心虚)
1.士兵守卫
独立集问题模版
1 /* 2 id:Dear_prince 3 */ 4 const int maxn=5000+5; 5 struct A 6 { 7 int v,next; 8 }e[maxn]; 9 int n,tot,ans,head[maxn],f[maxn][2]; 10 void add(int x,int y) 11 { 12 e[++tot].v=y; 13 e[tot].next=head[x]; 14 head[x]=tot; 15 } 16 void dp(int u,int fa) 17 { 18 f[u][0]=0,f[u][1]=1; 19 for(int i=head[u];i;i=e[i].next) 20 { 21 int v=e[i].v; 22 if(v==fa) 23 continue; 24 dp(v,u); 25 f[u][0]+=f[v][1]; 26 f[u][1]+=min(f[v][0],f[v][1]); 27 } 28 } 29 int main() 30 { 31 input(); 32 int x,y,m; 33 while(scanf("%d",&n)!=EOF) 34 { 35 for(int i=1;i<=n;i++) 36 { 37 x=quick(); 38 m=quick(); 39 for(int i=1;i<=m;i++) 40 { 41 y=quick(); 42 add(x,y); 43 add(y,x); 44 } 45 } 46 dp(0,-1); 47 printf("%d\n",min(f[0][1],f[0][0])); 48 tot=0; 49 for(int i=0;i<=n;i++) 50 head[i]=0; 51 } 52 return 0; 53 }
2.保卫王国
乱搞一通的44分代码
1 /* 2 id:Dear_prince 3 */ 4 const int maxn=2e5+5; 5 struct A 6 { 7 int v,next; 8 }e[maxn]; 9 int head[maxn],f[maxn][2],v[maxn],p[maxn]; 10 char t[3]; 11 int n,m,tot; 12 void add(int x,int y) 13 { 14 e[++tot].v=y; 15 e[tot].next=head[x]; 16 head[x]=tot; 17 } 18 void dp(int u,int fa) 19 { 20 if(f[u][0]!=INF) 21 f[u][0]=0; 22 if(f[u][1]!=INF) 23 f[u][1]=p[u]; 24 for(int i=head[u];i;i=e[i].next) 25 { 26 int vi=e[i].v; 27 if(vi==fa) 28 continue; 29 dp(vi,u); 30 if(f[u][1]==INF) 31 { 32 f[u][0]+=f[vi][1]; 33 v[u]=vi; 34 } 35 else if(f[u][0]==INF) 36 { 37 f[u][1]+=min(f[vi][0],f[vi][1]); 38 v[vi]=v[u]; 39 } 40 else 41 { 42 f[u][0]+=f[vi][1]; 43 f[u][1]+=min(f[vi][0],f[vi][1]); 44 } 45 } 46 } 47 void query(int a,int x,int b,int y) 48 { 49 f[a][(!x)]=f[b][(!y)]=INF; 50 dp(1,0); 51 if(!x&&!y&&(v[a]==b||v[b]==a)) 52 printf("-1\n"); 53 else printf("%d\n",min(f[1][0],f[1][1])); 54 for(int i=1;i<=n;i++) 55 f[i][0]=f[i][1]=v[i]=0; 56 } 57 int main() 58 { 59 input(); 60 int a,b,x,y; 61 n=quick(); 62 m=quick(); 63 scanf("%s",t); 64 for(int i=1;i<=n;i++) 65 p[i]=quick(); 66 for(int i=1;i<n;i++) 67 { 68 x=quick(); 69 y=quick(); 70 add(x,y); 71 add(y,x); 72 } 73 for(int i=1;i<=m;i++) 74 { 75 a=quick(); 76 x=quick(); 77 b=quick(); 78 y=quick(); 79 query(a,x,b,y); 80 } 81 return 0; 82 }
3.选课
有依赖的背包问题?
1 /* 2 id:Dear_prince 3 */ 4 const int maxn=302; 5 struct A 6 { 7 int v,next; 8 }e[maxn]; 9 int head[maxn],p[maxn],f[maxn][maxn]; 10 int n,m,tot; 11 void add(int x,int y) 12 { 13 e[++tot].v=y; 14 e[tot].next=head[x]; 15 head[x]=tot; 16 } 17 void read() 18 { 19 n=quick(); 20 m=quick(); 21 int x,y; 22 for(int y=1;y<=n;y++) 23 { 24 x=quick(); 25 add(x,y); 26 p[y]=quick(); 27 } 28 } 29 int dp(int u,int fa) 30 { 31 int size=1; 32 //f[u][0]=0; 33 f[u][1]=p[u]; 34 for(int i=head[u];i;i=e[i].next) 35 { 36 int v=e[i].v; 37 int s=dp(v,u); 38 size+=s; 39 for(int j=size;j>0;j--) 40 for(int k=0;k<j;k++) 41 { 42 if(k>s)break; 43 f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]); 44 } 45 } 46 return size; 47 } 48 void work() 49 { 50 dp(0,-1); 51 printf("%d",f[0][m+1]); 52 }
1 /* 2 id:Dear_prince 3 */ 4 const int maxn=1e6+5; 5 struct A 6 { 7 int v,next; 8 }e[maxn]; 9 int head[maxn],f[maxn][2],a[maxn]; 10 int n,ans,tot; 11 void add(int x,int y) 12 { 13 e[++tot].v=y; 14 e[tot].next=head[x]; 15 head[x]=tot; 16 } 17 void read() 18 { 19 n=quick(); 20 for(int i=1;i<=n;i++) 21 a[i]=quick(); 22 int x,y; 23 for(int i=1;i<n;i++) 24 { 25 x=quick(); 26 y=quick(); 27 add(x,y); 28 add(y,x); 29 } 30 } 31 int maxx(int x,int y,int z) 32 { 33 if(x>y) 34 y=x; 35 if(y>z) 36 z=y; 37 return z; 38 } 39 void dp(int u,int fa) 40 { 41 f[u][0]=0,f[u][1]=a[u]; 42 for(int i=head[u];i;i=e[i].next) 43 { 44 int v=e[i].v; 45 if(v==fa)continue; 46 dp(v,u); 47 if(f[v][1]>0) 48 f[u][1]+=f[v][1]; 49 } 50 ans=maxx(ans,f[u][1],f[u][0]); 51 } 52 void work() 53 { 54 dp(1,0); 55 printf("%d",ans); 56 }
5.二叉苹果树
一直卡在究竟是把权值赋边还是赋点上,其实都可以,赋边要难写一点,最后还是赋点解决了。。。
1 /* 2 id:Dear_prince 3 */ 4 const int maxn=205; 5 struct A 6 { 7 int v,w,next; 8 }e[maxn]; 9 int f[maxn][maxn],head[maxn]; 10 int n,q,tot; 11 void add(int x,int y,int z) 12 { 13 e[++tot].v=y; 14 e[tot].w=z; 15 e[tot].next=head[x]; 16 head[x]=tot; 17 } 18 void read() 19 { 20 n=quick(); 21 q=quick(); 22 int x,y,z; 23 for(int i=1;i<n;i++) 24 { 25 x=quick(); 26 y=quick(); 27 z=quick(); 28 add(x,y,z); 29 add(y,x,z); 30 } 31 } 32 int dp(int u,int fa,int c) 33 { 34 int size=1; 35 f[u][1]=c; 36 for(int i=head[u];i;i=e[i].next) 37 { 38 int v=e[i].v; 39 int w=e[i].w; 40 if(v==fa) 41 continue; 42 int s=dp(v,u,w); 43 size+=s; 44 for(int j=size;j>0;j--) 45 for(int k=0;k<j;k++) 46 { 47 if(k>s+1)break; 48 f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]); 49 } 50 } 51 return size; 52 } 53 void work() 54 { 55 dp(1,0,0); 56 printf("%d",f[1][q+1]); 57 }
6.战略游戏
1 /* 2 id:Dear_prince 3 */ 4 const int maxn=3002; 5 struct A 6 { 7 int v,next; 8 }e[maxn]; 9 int f[maxn][2],head[maxn]; 10 int n,tot; 11 void add(int x,int y) 12 { 13 e[++tot].v=y; 14 e[tot].next=head[x]; 15 head[x]=tot; 16 } 17 void read() 18 { 19 n=quick(); 20 int x,y,k; 21 for(int i=1;i<=n;i++) 22 { 23 x=quick(); 24 k=quick(); 25 for(int j=1;j<=k;j++) 26 { 27 y=quick(); 28 add(x,y); 29 add(y,x); 30 } 31 } 32 } 33 void dp(int u,int fa) 34 { 35 f[u][0]=0,f[u][1]=1; 36 for(int i=head[u];i;i=e[i].next) 37 { 38 int v=e[i].v; 39 if(v==fa) 40 continue; 41 dp(v,u); 42 f[u][0]+=f[v][1]; 43 f[u][1]+=min(f[v][1],f[v][0]); 44 } 45 } 46 void work() 47 { 48 dp(0,-1); 49 printf("%d",min(f[0][0],f[0][1])); 50 }
7.没有上司的舞会
很有意思的一道题,细看就是独立集问题吗,但不影响它是一道很有意思的裸题。
1 /* 2 id:Dear_prince 3 */ 4 const int maxn=12005; 5 struct A 6 { 7 int v,next; 8 }e[maxn]; 9 int head[maxn],f[maxn][2],a[maxn]; 10 int n,tot,ans; 11 void add(int x,int y) 12 { 13 e[++tot].v=y; 14 e[tot].next=head[x]; 15 head[x]=tot; 16 } 17 void read() 18 { 19 n=quick(); 20 for(int i=1;i<=n;i++) 21 a[i]=quick(); 22 int x,y; 23 for(int i=1;i<n;i++) 24 { 25 x=quick(); 26 y=quick(); 27 add(y,x); 28 add(x,y); 29 } 30 } 31 int maxx(int x,int y,int z) 32 { 33 if(x>y) 34 y=x; 35 if(y>z) 36 z=y; 37 return z; 38 } 39 void dp(int u,int fa) 40 { 41 f[u][0]=0,f[u][1]=a[u]; 42 for(int i=head[u];i;i=e[i].next) 43 { 44 int v=e[i].v; 45 if(v==fa) 46 continue; 47 dp(v,u); 48 f[u][0]+=max(f[v][1],f[v][0]); 49 f[u][1]+=f[v][0]; 50 } 51 } 52 void work() 53 { 54 dp(1,0); 55 printf("%d",max(f[1][0],f[1][1])); 56 }
8.Party at Hali-Bula
坑点在字符串处理和确定方案数是否唯一啊。。。
实在不想弄字符串了。。。
9.重建道路
开始没看样例,以为是求刚好断出p个点,就打了个不知道什么鬼,然后连样例都没过。。。
后来发现,这就是背包啊,反着做就好了。。。
原文:https://www.cnblogs.com/Achensy/p/10292624.html