4202. Shopping
来源:互联网 发布:声音放大器偷听软件 编辑:程序博客网 时间:2024/05/18 10:57
题目大意
给定一棵
现在要选出一个连通块使得价值最大。
Data Constraint
题解
考虑点剖,每次选择重心就进行多重背包DP。
如果不选择就递归进子树继续考虑。
每次DP的时候是一个树型依赖DP,可以在DFS序上DP,每次选择一个点
注意要按二的幂将物品分组。
SRC
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std ;#define N 500 + 10#define M 4000 + 10const int inf = 0x7FFFFFFF ;struct Object { int w , c , d ;} P[N] ;bool vis[N] ;int Node[2*N] , Next[2*N] , Head[N] , tot ;int W[20*N] , V[20*N] , st[N] , ed[N] ;int DFN[N] , S[N] , R[N] , Size[N] , Maxs[N] ;int f[N][M] , g[M] ;int T , n , m , q , ans ;int Root , All , Cnt , Minv ;void link( int u , int v ) { Node[++tot] = v ; Next[tot] = Head[u] ; Head[u] = tot ;}void DP() { int Num = 0 ; for (int i = 1 ; i <= Cnt ; i ++ ) { for (int j = 0 ; j <= m ; j ++ ) f[i][j] = -inf ; int now = S[i] ; if ( i == 1 ) { if ( !P[now].d ) return ; for (int k = 1 ; k <= P[now].d ; k ++ ) f[1][k*P[now].c] = k * P[now].w ; continue ; } int x = P[now].d - 1 , k = 1 ; st[i] = Num + 1 ; while ( x >= k ) { ++ Num ; W[Num] = P[now].w * k ; V[Num] = P[now].c * k ; x -= k ; k *= 2 ; } if ( x ) { ++ Num ; W[Num] = P[now].w * x ; V[Num] = P[now].c * x ; } ed[i] = Num ; } for (int i = 2 ; i <= Cnt ; i ++ ) { for (int j = m ; j >= 0 ; j -- ) { if ( j >= P[S[i]].c ) g[j] = f[i-1][j-P[S[i]].c] + P[S[i]].w ; else g[j] = -inf ; } for (int k = st[i] ; k <= ed[i] ; k ++ ) { for (int j = m ; j >= V[k] ; j -- ) g[j] = max( g[j] , g[j-V[k]] + W[k] ) ; } for (int j = 0 ; j <= m ; j ++ ) f[i][j] = max( f[i][j] , g[j] ) ; for (int k = 0 ; k <= m ; k ++ ) f[R[S[i]]][k] = max( f[R[S[i]]][k] , f[i-1][k] ) ; } for (int i = 1 ; i <= Cnt ; i ++ ) for (int j = 0 ; j <= m ; j ++ ) ans = max( ans , f[i][j] ) ;}void GetSize( int x , int F ) { Size[x] = Maxs[x] = 1 ; for (int p = Head[x] ; p ; p = Next[p] ) { if ( Node[p] == F || vis[Node[p]] ) continue ; GetSize( Node[p] , x ) ; Size[x] += Size[Node[p]] ; if ( Size[Node[p]] > Maxs[x] ) Maxs[x] = Size[Node[p]] ; }}void GetRoot( int x , int F ) { Maxs[x] = max( Maxs[x] , Size[All] - Size[x] ) ; if ( Maxs[x] < Minv ) Minv = Maxs[x] , Root = x ; for (int p = Head[x] ; p ; p = Next[p] ) { if ( Node[p] == F || vis[Node[p]] ) continue ; GetRoot( Node[p] , x ) ; }}void DFS( int x , int F ) { DFN[x] = R[x] = ++ Cnt ; S[Cnt] = x ; for (int p = Head[x] ; p ; p = Next[p] ) { if ( Node[p] == F || vis[Node[p]] ) continue ; DFS( Node[p] , x ) ; R[x] = R[Node[p]] ; }}void DIV( int x ) { Minv = 0x7FFFFFFF ; Root = All = x ; GetSize( x , 0 ) ; GetRoot( x , 0 ) ; Cnt = 0 ; DFS( Root , 0 ) ; DP() ; vis[Root] = 1 ; for (int p = Head[Root] ; p ; p = Next[p] ) { if ( vis[Node[p]] ) continue ; DIV( Node[p] ) ; }}int main() { freopen( "shopping.in" , "r" , stdin ) ; freopen( "shopping.out" , "w" , stdout ) ; scanf( "%d" , &T ) ; while ( T -- ) { tot = ans = 0 ; memset( vis , 0 , sizeof(vis) ) ; memset( Head , 0 , sizeof(Head) ) ; scanf( "%d%d" , &n , &m ) ; for (int i = 1 ; i <= n ; i ++ ) scanf( "%d" , &P[i].w ) ; for (int i = 1 ; i <= n ; i ++ ) scanf( "%d" , &P[i].c ) ; for (int i = 1 ; i <= n ; i ++ ) scanf( "%d" , &P[i].d ) ; for (int i = 1 ; i < n ; i ++ ) { int u , v ; scanf( "%d%d" , &u , &v ) ; link( u , v ) , link( v , u ) ; } DIV( 1 ) ; printf( "%d\n" , ans ) ; } return 0 ;}
以上.
0 0
- 4202. Shopping
- shopping
- shopping
- Shopping
- Shopping
- shopping
- Shopping
- Shopping 购物
- Shopping feast
- shopping list
- Shopping Offers
- [ACM]Shopping
- Shopping Offers
- HK shopping
- codeforces_665B. Shopping
- Beg-Shopping
- [bzoj4182]Shopping
- Shopping CodeForces
- idea使用maven配置下载镜像(解决依赖文件下载不动的问题)
- 孙鑫VC++ 第三课 this指针的问题
- C#如何将ListView中的数据导出到Excel中
- HDU 3338 Kakuro Extension(最大流,拆点)
- c语言编程中的一点小技巧(老司机专用)
- 4202. Shopping
- Vue.js学习系列(四十二)-- Vue.js组件
- 【机器学习 基本概念】朴素贝叶斯分类
- BC
- javascript继承
- python爬虫入门笔记:用scrapy爬豆瓣
- 509_各种控件效果统计
- MySQL使用之修改字符集
- oc总结 --oc基础语法相关知识