zoukankan      html  css  js  c++  java
  • [bzoj4182]Shopping

    题目连接

    暴力dp时间复杂度为$o(nm^{2})$,是不行的

    考虑当我们强制该连通块包含根,可以直接在dfs序上dp,即若该点选则考虑从$f_{i+1}$转移,否则从其子树所对应区间右端点+1来转移(即$f_{dfn_{x}+sz_{x}}$),利用单调队列优化可做到$o(nm)$

    之后对其点分治即可,时间复杂度为$o(nmlog_{2}n)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 505
     4 #define M 4005
     5 struct ji{
     6     int nex,to;
     7 }edge[N<<1];
     8 deque<int>q[M];
     9 int E,t,n,m,r,x,y,ans,w[N],c[N],d[N],head[N],vis[N],sz[N],dfn[N],f[N][M];
    10 void add(int x,int y){
    11     edge[E].nex=head[x];
    12     edge[E].to=y;
    13     head[x]=E++;
    14 }
    15 void tot(int k,int fa){
    16     sz[k]=1;
    17     for(int i=head[k];i!=-1;i=edge[i].nex)
    18         if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
    19             tot(edge[i].to,k);
    20             sz[k]+=sz[edge[i].to];
    21         }
    22 }
    23 void find(int k,int fa,int s){
    24     int mx=s-sz[k];
    25     for(int i=head[k];i!=-1;i=edge[i].nex)
    26         if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
    27             find(edge[i].to,k,s);
    28             mx=max(mx,sz[edge[i].to]);
    29         }
    30     if (mx<=s/2)r=k;
    31 }
    32 void get_root(int k){
    33     tot(k,0);
    34     find(k,0,sz[k]);
    35 }
    36 void dfs(int k,int fa){
    37     dfn[++dfn[0]]=k;
    38     sz[k]=1;
    39     for(int i=head[k];i!=-1;i=edge[i].nex)
    40         if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
    41             dfs(edge[i].to,k);
    42             sz[k]+=sz[edge[i].to];
    43         }
    44 }
    45 void calc(int k){
    46     dfn[0]=0;
    47     dfs(k,0);
    48     for(int i=0;i<=m;i++)f[dfn[0]+1][i]=0;
    49     for(int i=dfn[0];i;i--){
    50         int x=dfn[i];
    51         for(int j=0;j<=m;j++)f[i][j]=f[i+sz[x]][j];
    52         if (c[x]>m)continue;
    53         for(int j=0;j<c[x];j++)q[j].clear();
    54         for(int j=0;j<=m;j++){
    55             int p=j%c[x];
    56             while ((!q[p].empty())&&(q[p].front()<j-d[x]*c[x]))q[p].pop_front();
    57             if (!q[p].empty()){
    58                 int y=q[p].front();
    59                 f[i][j]=max(f[i][j],f[i+1][y]+(j-y)/c[x]*w[x]);
    60             }
    61             while (!q[p].empty()){
    62                 int y=q[p].back();
    63                 if (f[i+1][y]+(j-y)/c[x]*w[x]>=f[i+1][j])break;
    64                 q[p].pop_back();
    65             }
    66             q[p].push_back(j);
    67         }
    68     }
    69     ans=max(ans,f[1][m]);
    70 }
    71 void dfs(int k){
    72     if (vis[k])return;
    73     get_root(k);
    74     calc(r);
    75     vis[r]=1;
    76     for(int i=head[r];i!=-1;i=edge[i].nex)dfs(edge[i].to);
    77 }
    78 int main(){
    79     scanf("%d",&t);
    80     while (t--){
    81         scanf("%d%d",&n,&m);
    82         for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    83         for(int i=1;i<=n;i++)scanf("%d",&c[i]);
    84         for(int i=1;i<=n;i++)scanf("%d",&d[i]);
    85         E=ans=0;
    86         memset(head,-1,sizeof(head));
    87         for(int i=1;i<n;i++){
    88             scanf("%d%d",&x,&y);
    89             add(x,y);
    90             add(y,x);
    91         }
    92         memset(vis,0,sizeof(vis));
    93         dfs(1);
    94         printf("%d
    ",ans);
    95     }
    96 } 
    View Code
  • 相关阅读:
    Java知识体系总结(2021版)
    第三篇 makefile的伪目标
    第二篇 makefile的基本结构
    第一篇 make与makefile介绍
    hdu 1994 利息计算
    Python中Class中的object是什么意思?
    编译语言和解释语言有什么不同?
    从文本文件hello.txt到可执行文件hello
    classmethod和staticmethod
    Uninstall NetBeans
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14318083.html
Copyright © 2011-2022 走看看