zoukankan      html  css  js  c++  java
  • 树型dp(2019/1/19学习笔记) by csy

    树型dp(2019/1/19学习笔记)

    全文代码已去掉非关键部分,请勿复制粘贴

    总结:树型dp的套路掌握后代码难度不大,难度在于对状态和标记的维护。就是做了一天简单的题有点心虚

    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
    ",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
    ");
    53     else printf("%d
    ",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 }

    4.最大子树和

    太简单了,都不想写。。。

     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个点,就打了个不知道什么鬼,然后连样例都没过。。。

    后来发现,这就是背包啊,反着做就好了。。。

     附上76分代码,从43分写到56分再到76分也不容易啊,说不定哪天就ac啦

     1 /*
     2 id:Dear_prince 
     3 */
     4 #define INF 0x3f3f3f3f
     5 const int maxn=305;
     6 struct A
     7 {
     8     int v,next;
     9 }e[maxn];
    10 int head[maxn],f1[maxn][maxn],f2[maxn][maxn];
    11 int n,q,tot,ans=INF;
    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 read()
    19 {
    20     memset(f1,0x3f,sizeof(f1));
    21     memset(f2,0x3f,sizeof(f2));
    22     n=quick();
    23     q=quick();
    24     int x,y;
    25     for(int i=1;i<n;i++)
    26     {
    27         x=quick();
    28         y=quick();
    29         add(x,y);
    30         add(y,x);
    31     }
    32 }
    33 int minn(int x,int y,int z)
    34 {
    35     if(x<y)
    36         y=x;
    37     if(y<z)
    38         z=y;
    39     return z;
    40 }
    41 int dp(int u,int fa)
    42 {
    43     int size=1,cnt=0;
    44     f1[u][0]=f2[u][0]=0;
    45     for(int i=head[u];i;i=e[i].next)
    46     {
    47         int v=e[i].v;
    48         if(v==fa)
    49             continue;
    50         int s=dp(v,u);
    51         size+=s;
    52         /*for(int j=size;j>0;j--)
    53             for(int k=0;k<j;k--)
    54             {
    55                 if(k>s)
    56                     break;
    57             }*/
    58         f1[u][s]=1;
    59     }
    60     for(int i=1;i<=size;i++)
    61         for(int j=1;j<=size-i;j++)
    62             f2[u][i+j]=minn(min(f1[u][i],f2[u][i])+min(f1[u][j],f2[u][j]),f1[u][i+j],f2[u][i+j]);
    63     return size;
    64 }
    65 void work()
    66 {
    67     dp(1,0);
    68     for(int i=1;i<=n;i++)
    69             ans=minn(f2[i][n-q],ans,f1[i][q]);
    70     printf("%d",ans);
    71 }
  • 相关阅读:
    Linux命令学习Day1
    谈谈VAssitX Snippet
    Visual Studio sort函数出现“invalid operator<”原因分析
    网络打印机共享设置
    Notepad++使用总结
    Leetcode顺时钟旋转90度
    搭建Docker版gitlab私有云
    获取安卓APP设备上报信息
    中间件服务测试点整理
    Jenkins主从模式添加节点机
  • 原文地址:https://www.cnblogs.com/Achensy/p/10292624.html
Copyright © 2011-2022 走看看