About Tree Backpack

Posted by jmugambi on Wed, 31 Jul 2019 04:19:23 +0200

Backpack is a simple DP, so it's not easy to put it on a tree.

Tree Backpack Primary Practice:

Suppose f[i][j] is rooted in I node and the volume is the maximum benefit of I. In fact, f[u][i][j] means taking u as the root and selecting I subtrees, the volume of which is the maximum benefit of J. However, through the one-dimensional inverted cycle of volume (like 01 knapsack), it can be optimized to O (n^2) in space, but in time, it is still very large, O(n^3).

F [i] [j] = max (f [i] [j], f [i] [j], f [i] [j-k] + F [v] [k]) (cyclic J inversion, K from 0 to j.)  

The answer is f [root] [knapsack volume]

Then there is optimization:

Let f[i][j] denote that the dfs order is from I to tot, and the volume is the maximum value of J.

The siz of each subtree is calculated once by dfs, and the mapping of each DFS sequence to the original number is established. (id[++num]=x).

F [i] [j] = max (f [i + siz [i]] [j], f [i + 1] [j-w [i] + val [i]) (cyclic I inversion)

The answer is f[1] [knapsack volume]

There are other optimizations, but I won't...

The following is the code:

Examples Luogu P2515 [HAOI2010] Software Installation

 

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define RE register
 4 using namespace std;
 5 const int maxn=2200;
 6 inline int R(){
 7     RE char b=getchar();int x=0,t=1;
 8     while(b<'0'||b>'9'){if(b=='-') t=-1;b=getchar();}
 9     while(b>='0'&&b<='9') {x=(x<<3)+(x<<1)+b-'0';b=getchar();}
10     return x*t;
11 }
12 struct Edge{
13     int nxt,to;
14 }ed[maxn];
15 int head[maxn],ecnt;
16 void addedge(int f,int to){
17     ed[++ecnt].to=to;
18     ed[ecnt].nxt=head[f];
19     head[f]=ecnt;
20 }
21 int n,m;
22 int w[maxn],v[maxn],d[maxn];
23 int ww[maxn],vv[maxn],rd[maxn];
24 int siz[maxn];
25 int f[maxn][maxn];
26 void dfs(int x){// Focusing
27     for(int i=ww[x];i<=m;i++) f[x][i]=vv[x];
28 //    f[x][ww[x]]=vv[x];
29     for(int i=head[x];i;i=ed[i].nxt){
30         int v=ed[i].to;
31         dfs(v);
32         for(int j=m-ww[x];j>=0;j--) for(int k=0;k<=j;k++){
33             f[x][j+ww[x]]=max(f[x][j+ww[x]],f[x][j+ww[x]-k]+f[v][k]);
34         }
35     }
36 }
37 int dfn[maxn],low[maxn],num;
38 bool vis[maxn];
39 int sta[maxn],tp;
40 int scc_num,scc[maxn];
41 void tarjan(int x){
42     sta[++tp]=x;
43     vis[x]=1;
44     dfn[x]=low[x]=++num;
45     for(int i=head[x];i;i=ed[i].nxt){
46         int v=ed[i].to;
47         if(!dfn[v]){
48             tarjan(v);
49             low[x]=min(low[x],low[v]);
50         }
51         else if(vis[v]) low[x]=min(low[x],dfn[v]);
52     }
53     if(low[x]==dfn[x]){
54         scc_num++;
55         int tmp;
56         do{
57             tmp=sta[tp--];
58             vis[tmp]=0;
59             scc[tmp]=scc_num;
60             ww[scc_num]+=w[tmp];
61             vv[scc_num]+=v[tmp];
62         }while(tmp!=x);
63     }
64 }
65 int main(){
66     n=R(),m=R();
67     for(int i=1;i<=n;i++) w[i]=R();
68     for(int i=1;i<=n;i++) v[i]=R();
69     for(int i=1;i<=n;i++){
70         d[i]=R();
71         if(d[i]) addedge(d[i],i);
72     }
73     for(int i=1;i<=n;i++){
74         if(!dfn[i]) tarjan(i);
75     }
76     memset(head,0,sizeof head);
77     memset(ed,0,sizeof ed);ecnt=0;
78     for(int i=1;i<=n;i++){
79         int f=d[i],to=i;
80         if(scc[f]!=scc[to]&&f) addedge(scc[f],scc[to]),rd[scc[to]]++;
81     }
82     for(int i=1;i<=scc_num;i++)
83         if(!rd[i]) addedge(scc_num+1,i);//Must first shrink point and super source point, otherwise the ring will not be connected to super source point. 
84     dfs(scc_num+1);
85     printf("%d\n",f[scc_num+1][m]);
86     return 0;
87 }
simple

 

  1 #include<bits/stdc++.h>
  2 #define ll long long
  3 #define RE register
  4 using namespace std;
  5 const int maxn=2200;
  6 inline int R(){
  7     RE char b=getchar();int x=0,t=1;
  8     while(b<'0'||b>'9'){if(b=='-') t=-1;b=getchar();}
  9     while(b>='0'&&b<='9') {x=(x<<3)+(x<<1)+b-'0';b=getchar();}
 10     return x*t;
 11 }
 12 struct Edge{
 13     int nxt,to;
 14 }ed[maxn];
 15 int head[maxn],ecnt;
 16 void addedge(int f,int to){
 17     ed[++ecnt].to=to;
 18     ed[ecnt].nxt=head[f];
 19     head[f]=ecnt;
 20 }
 21 int n,m;
 22 int w[maxn],v[maxn],d[maxn];
 23 int ww[maxn],vv[maxn],rd[maxn];
 24 int siz[maxn];
 25 int f[maxn][maxn];
 26 //void dfs(int x){
 27 //    for(int i=ww[x];i<=m;i++) f[x][i]=vv[x];
 28 ////    f[x][ww[x]]=vv[x];
 29 //    for(int i=head[x];i;i=ed[i].nxt){
 30 //        int v=ed[i].to;
 31 //        dfs(v);
 32 //        for(int j=m-ww[x];j>=0;j--) for(int k=0;k<=j;k++){
 33 //            f[x][j+ww[x]]=max(f[x][j+ww[x]],f[x][j+ww[x]-k]+f[v][k]);
 34 //        }
 35 //    }
 36 //}
 37 int id[maxn],num;
 38 void dfs(int x){
 39     id[++num]=x;//Focusing
 40     siz[x]=1;
 41     for(int i=head[x];i;i=ed[i].nxt){
 42         int v=ed[i].to;
 43         dfs(v);
 44         siz[x]+=siz[v];
 45     }
 46 }
 47 int dfn[maxn],low[maxn];
 48 bool vis[maxn];
 49 int sta[maxn],tp;
 50 int scc_num,scc[maxn];
 51 void tarjan(int x){
 52     sta[++tp]=x;
 53     vis[x]=1;
 54     dfn[x]=low[x]=++num;
 55     for(int i=head[x];i;i=ed[i].nxt){
 56         int v=ed[i].to;
 57         if(!dfn[v]){
 58             tarjan(v);
 59             low[x]=min(low[x],low[v]);
 60         }
 61         else if(vis[v]) low[x]=min(low[x],dfn[v]);
 62     }
 63     if(low[x]==dfn[x]){
 64         scc_num++;
 65         int tmp;
 66         do{
 67             tmp=sta[tp--];
 68             vis[tmp]=0;
 69             scc[tmp]=scc_num;
 70             ww[scc_num]+=w[tmp];
 71             vv[scc_num]+=v[tmp];
 72         }while(tmp!=x);
 73     }
 74 }
 75 int main(){
 76     n=R(),m=R();
 77     for(int i=1;i<=n;i++) w[i]=R();
 78     for(int i=1;i<=n;i++) v[i]=R();
 79     for(int i=1;i<=n;i++){
 80         d[i]=R();
 81         if(d[i]) addedge(d[i],i);
 82     }
 83     for(int i=1;i<=n;i++){
 84         if(!dfn[i]) tarjan(i);
 85     }
 86     memset(head,0,sizeof head);
 87     memset(ed,0,sizeof ed);ecnt=0;
 88     for(int i=1;i<=n;i++){
 89         int f=d[i],to=i;
 90         if(scc[f]!=scc[to]&&f) addedge(scc[f],scc[to]),rd[scc[to]]++;
 91     }
 92     for(int i=1;i<=scc_num;i++)
 93         if(!rd[i]) addedge(scc_num+1,i);//Must first shrink point and super source point, otherwise the ring will not be connected to super source point. 
 94     memset(dfn,0,sizeof dfn);num=0;
 95     dfs(scc_num+1);
 96     for(int i=num;i;i--){//Focusing
 97         for(int j=0;j<=m;j++)
 98         if(j-ww[id[i]]>=0) f[i][j]=max(f[i+siz[id[i]]][j],f[i+1][j-ww[id[i]]]+vv[id[i]]);//Focusing
 99         else f[i][j]=f[i+siz[id[i]]][j];//Focus on --- Especially
100     }
101     printf("%d\n",f[1][m]);//Focusing
102     return 0;
103 }
dfs order

The reason why I've been working on this question all afternoon is that... Tarjan was wrong.

Topics: PHP