树形DP集锦2
来源:互联网 发布:归并排序 c语言 编辑:程序博客网 时间:2024/06/16 09:52
一共有n(<=200)个国家, 你想要至少收买m(<=m)个国家,其中收买国家i的代价是w[ i ]。但是有些国家有拥属关系,如果A拥属B国,就是买通了A也意味着买通了B,而且这些关系是传递的。求最少需要付出的代价。(poj)
读入有点意思。
const int maxn = 208 ;int n , m ;vector<int> g[maxn] ;int w[maxn] ;int dp[maxn][maxn] , son[maxn] ;void dfs(int u){ son[u] = 1 ; dp[u][0] = 0 ; for(int i = 0 ; i < g[u].size() ; i++){ int v = g[u][i] ; dfs(v) ; for(int k = n ; k >= 0 ; k--){ for(int j = 0 ; j <= k ; j++) dp[u][k] = min(dp[u][k] , dp[u][k-j] + dp[v][j]) ; } son[u] += son[v] ; } dp[u][son[u]] = min(dp[u][son[u]] , w[u]) ;}int in[maxn] ;char str[1008] ;map<string , int> h ;int main(){ int i , id , u , v ; while(gets(str)){ if(str[0] == '#') break ; sscanf(str , "%d%d" ,&n ,&m) ; for(i = 0 ; i <= n ; i++) g[i].clear() ; h.clear() ; id = 0 ; memset(in , 0 , sizeof(in)) ; memset(son , 0 , sizeof(son)) ; memset(dp , 63 , sizeof(dp)) ; //最大值inf for(i = 1 ; i <= n ; i++){ scanf("%s" ,str) ; if(h.find(str) == h.end()) h[str] = ++id ; u = h[str] ; scanf("%d" ,&w[u]) ; gets(str) ; stringstream s(str) ; string name ; while(s>>name){ if(h.find(name) == h.end()) h[name] = ++id ; v = h[name] ; g[u].push_back(v) ; in[v]++ ; } } for(i = 1 ; i <= n ; i++){ if(in[i]==0) g[0].push_back(i) ; } dfs(0) ; int s = dp[0][m] ; for(i = m ; i <= n ; i++) s = min(s , dp[0][i]) ; printf("%d\n" , s) ; } return 0 ;}
给出一个大小为n的树,几每个节点的权值。问这棵树中大小m的子树最大权值。(zoj)
const int maxn = 108 ;vector<int> g[maxn] ;int dp[maxn][maxn] ;int n , m ;bool vis[maxn] ;void dfs(int u){ vis[u] = 1 ; for(int i = 0 ; i < g[u].size() ; i++){ int v = g[u][i] ; if(vis[v]) continue ; dfs(v) ; for(int j = m ; j > 1 ; j--){ for(int k = 1 ; k < j ; k++) dp[u][j] = max(dp[u][j] , dp[u][j-k] + dp[v][k]) ; } }}int main(){ int i , u , v ; while(scanf("%d%d" ,&n ,&m) != EOF){ for(i = 0 ; i <= n ; i++) g[i].clear() ; memset(vis , 0 , sizeof(vis)) ; memset(dp , 0 , sizeof(dp)) ; for(i = 0 ; i < n ; i++) scanf("%d" ,&dp[i][1]) ; for(i = 1 ; i < n ; i++){ scanf("%d%d" ,&u ,&v) ; g[u].push_back(v) ; g[v].push_back(u) ; } int s = 0 ; dfs(0) ; for(i = 0 ; i < n ; i++) s = max(s , dp[i][m]) ; printf("%d\n" ,s) ; } return 0 ;}
给出一棵树,问最少切断几条边可以得到有p个结点的子树。(poj)
dp[i][j]表示以第i个节点为根的子树保留j个节点最少需要去掉几条边
const int maxn = 158 ;vector<int> g[maxn] ;int dp[maxn][maxn] ;int m ;void dfs(int u , int father){ dp[u][1] = 0 ; for(int i = 0 ; i < g[u].size() ; i++){ int v = g[u][i] ; if(v == father) continue ; dfs(v , u) ; for(int j = m ; j >= 1 ; j--){ dp[u][j] = dp[u][j] + 1 ; for(int k = 1 ; k < j ; k++) dp[u][j] = min(dp[u][j] , dp[u][j-k] + dp[v][k]) ; } }}int main(){ int i , n , u , v , s ; while(cin>>n>>m){ for(i = 1 ; i <= n ; i++) g[i].clear() ; for(i = 1 ; i < n ; i++){ scanf("%d%d" ,&u ,&v) ; g[u].push_back(v) ; g[v].push_back(u) ; } memset(dp , 63 , sizeof(dp)) ; dfs(1, -1) ; s = dp[1][m] ; for(i = 2 ; i <= n ; i++) s = min(s , dp[i][m] + 1) ; printf("%d\n" ,s) ; } return 0 ;}
树,给每个结点的value 和 weight 。求容量为m的背包,能获得的最大value。选择了父结点才能选择子结点。m = 0时 ,输出0 。
const int maxn = 108 ;vector<int> g[maxn] ;int w[maxn] , val[maxn] ;int dp[maxn][maxn] ;int m ;void dfs(int u , int father){ for(int i = w[u] ; i <= m ; i++) dp[u][i] = val[u] ; for(int e = 0 ; e < g[u].size() ; e++){ int v = g[u][e] ; if(v == father) continue ; dfs(v , u) ; for(int i = m ; i >= w[u] ; i--){ for(int j = 1 ; i-j >= w[u] ; j ++) //必须选父亲 dp[u][i] = max( dp[u][i] , dp[u][i-j]+dp[v][j] ) ; } }}int main(){ int n , i , u , v ; while(cin>>n>>m){ if(n==-1 && m==-1) break ; for(i = 1 ; i <= n ; i++) g[i].clear() ; for(i = 1 ; i <= n ; i++){ scanf("%d%d" ,&w[i] , &val[i]) ; w[i] = (w[i]+19)/20 ; } for(i = 1 ; i < n ; i++){ scanf("%d%d" ,&u ,&v) ; g[u].push_back(v) ; g[v].push_back(u) ; } if(m == 0){puts("0") ; continue ; } memset(dp , 0 , sizeof(dp)) ; dfs(1 , -1) ; printf("%d\n" , dp[1][m]) ; } return 0 ;}
0 0
- 树形DP集锦2
- 树形DP集锦
- 树形DP初步(2)
- 树形dp
- 树形DP
- 树形dp
- 树形DP
- 树形dp
- 树形DP
- 树形DP
- 树形DP
- 树形DP
- 树形dp
- 树形dp
- 树形dp
- 树形dp
- 树形DP
- 树形DP
- 冒泡排序算法
- ios异步加载头像
- Android消息机制--Handler(待写)
- WSDL解析
- win7 桌面鼠标失效
- 树形DP集锦2
- 命令行(crontab) 调用 Yii 控制器
- linux下mysql远程连接问题,权限分配
- [svn]linux下"没有设置 SVN_EDITOR...."错误解决方法
- 第十周周报
- linux下安装配置tomcat以及tomcat开机自启配置
- 公众号、订阅号与服务号区别(微信5.0以上)
- 经典三级缓存(代码中注释很多)
- [python]集合