老师让我们补做了一下PKUSC那周的题目= =
这次好像是树形DP的专题?感觉题目还是很棒的,值得将来再回头学习。
Cateran
树形状压DP,其实在看题解之前我似乎并没有搞懂这题在干什么……
对于节点 i ,我们考虑f[i][j]表示 i 这棵子树中,分部包含情况为 j 的最大收益,因为一个分部管的是从x到根的所有点,所以对于一个点来说,管它的就是子树中的所有分部,所以就可以dp啦~依次枚举每个儿子的子树中有哪些分部,用一个辅助数组,我们可以搞:
c[j]=f[x][j];
c[j]=max(c[j],f[y][k]+f[x][j^k]);
f[x][j]=c[j];
依次搞下来即可。
初始化就是分部全部在 x 节点。计算完后要加上符合的收益(T种中的某一些……)
1 //20150527 cateran 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<iostream> 6 #include<algorithm> 7 #define rep(i,n) for(int i=0;i<n;++i) 8 #define F(i,j,n) for(int i=j;i<=n;++i) 9 #define D(i,j,n) for(int i=j;i>=n;--i) 10 #define pb push_back 11 using namespace std; 12 typedef long long LL; 13 inline int getint(){ 14 int r=1,v=0; char ch=getchar(); 15 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 16 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 17 return r*v; 18 } 19 const int N=4100; 20 /*******************template********************/ 21 22 int head[110],nxt[220],to[220],cnt; 23 void add(int x,int y){ 24 to[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt; 25 to[++cnt]=x; nxt[cnt]=head[y]; head[y]=cnt; 26 } 27 int n,m,T,a[110][15],b[N],c[N]; 28 int f[110][N]; 29 30 void dfs(int x,int fa){ 31 rep(j,(1<<m)){ 32 f[x][j]=0; 33 rep(i,m) if (j&(1<<i)) f[x][j]-=a[x][i+1]; 34 // printf("f[%d][%d]=%d\n",x,j,f[x][j]); 35 } 36 int y; 37 for(int i=head[x];i;i=nxt[i]) 38 if ((y=to[i])!=fa){ 39 dfs(y,x); 40 rep(j,(1<<m)) c[j]=f[x][j]; 41 rep(j,(1<<m)) 42 for(int k=j;k;k=(k-1)&j) 43 c[j]=max(c[j],f[y][k]+f[x][j^k]); 44 rep(j,1<<m) f[x][j]=c[j]; 45 } 46 rep(i,1<<m) 47 for(int k=i;k;k=(k-1)&i) f[x][i]+=b[k]; 48 // rep(i,1<<m) printf("f[%d][%d]=%d\n",x,i,f[x][i]); 49 } 50 int main(){ 51 #ifndef ONLINE_JUDGE 52 freopen("cateran.in","r",stdin); 53 freopen("cateran.out","w",stdout); 54 #endif 55 n=getint(); m=getint(); 56 F(i,2,n){ 57 int x=getint(),y=getint(); 58 add(x,y); 59 } 60 F(i,1,n) F(j,1,m) a[i][j]=getint(); 61 T=getint(); 62 F(i,1,T){ 63 int v=getint(),c=getint(),now=0,x; 64 F(j,1,c){ 65 x=getint(); 66 now|=1<<(x-1); 67 } 68 b[now]+=v; 69 } 70 dfs(1,0); 71 printf("%d\n",f[1][(1<<m)-1]); 72 return 0; 73 }