树状DP
紫皮,各种,非原创
树状数组在我的理解就是在决策过程中具有层次关系,像是树一样,具有上下级关系或者上级对上级一定程度的限制条件
uva 12186
工人的请愿书
下属中不小于 T% 的人签字时会签字递给上级,问至少需要多少人签字才能传给老板
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <cmath>
- #include <algorithm>
- #include <cstdlib>
- #include <map>
- #include <queue>
- #include <vector>
- const int MAXN = + ;
- const double ESP = 10e-;
- const double Pi = atan(1.0) * ;
- const int INF = 0xffffff;
- const int MOD = ;
- typedef long long LL;
- using namespace std;
- vector<int>sons[MAXN];
- int n,T;
- int dp(int u){
- if(sons[u].empty()){
- return ;
- }
- int k = sons[u].size();
- vector<int>d;
- for(int i = ;i < k;i++){
- d.push_back(dp(sons[u][i]));
- }
- sort(d.begin(),d.end());
- int c = (k*T - ) / + ;
- int ans = ;
- for(int i = ;i < c;i++){
- ans += d[i];
- }
- return ans;
- }
- int main(){
- //freopen("input.txt","r",stdin);
- while(~scanf("%d%d",&n,&T)){
- if(!n && !T){
- break;
- }
- for(int i = ;i <= n;i++){
- sons[i].clear();
- }
- for(int i = ;i <= n;i++){
- int a;
- scanf("%d",&a);
- sons[a].push_back(i);
- }
- printf("%d\n",dp());
- }
- return ;
- }
poj 3442 / uva 1220 Party at Hali-Bula
晚会邀请人,但是上下级不能在一起,求最多能邀请多少人,并且方案是否唯一
d(u,1) 邀请了u,所以其下级不能邀请 所以d(u,1) = sum(d(v,0) );
d(u,0) 没有邀请u,所以其下级,可以邀请也可以不邀请 则 d(u,0) = sum{ max( d(v,0),d(v,1) ) };
f(u,0) 为 1表示不唯一,否则唯一
f(u,1) 表示邀请了u,其方案是否唯一,当f(v,0)不唯一时,则f(u,1)必须不唯一
f(u,0) 没邀请 u 的方案是否唯一,如果 d(v,1) == d(v,0) 或者 由其所取的值得f(v)决定
- #include <iostream>
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <algorithm>
- #include <cstdlib>
- #include <stack>
- #include <cctype>
- #include <string>
- #include <queue>
- #include <map>
- #include <set>
- using namespace std;
- const int INF = 0xffffff;
- const double ESP = 10e-;
- const double Pi = * atan(1.0);
- const int MAXN = + ;
- const long long MOD = ;
- const int dr[] = {,,-,,-,,-,};
- const int dc[] = {,,,-,,-,-,};
- typedef long long LL;
- LL gac(LL a,LL b){
- return b?gac(b,a%b):a;
- }
- int n;
- int d[MAXN][];
- int child[MAXN];
- bool f[MAXN][];
- int cnt;
- map<string,int>m;
- vector<int>G[MAXN];
- int getNum(string str){
- int a;
- if(m.count(str)){
- a = m[str];
- }
- else{
- a = cnt;
- m[str] = cnt++;
- }
- return a;
- }
- void dp(int r){
- if(!G[r].size()){ //没有孩子
- d[r][] = ;//如果选择r能获得的最大值
- d[r][] = ; //如果不选择r获得的最大值
- // f[r][1] = 1;
- // f[r][0] = 1;
- return;
- }
- d[r][] = ; //如果选择了r则包含r这个员工
- bool flag = ;
- // f[r][0] = 1;
- int len = G[r].size();
- for(int l = ;l < len;l++){
- dp(G[r][l]);
- int i = G[r][l];
- if(f[i][]){
- f[r][] = ;
- }
- d[r][] += d[i][];
- if(d[i][] > d[i][]){
- d[r][] += d[i][];
- if(f[i][])
- f[r][] = ;
- }
- else{
- d[r][] += d[i][];
- if(d[i][] == d[i][] || f[i][])
- f[r][] = ;
- }
- // if(G[r][i]){
- // dp(i);
- // if(f[i][0]){
- // f[r][1] = 1;
- // }
- // d[r][1] += d[i][0];
- // if(d[i][0] > d[i][1]){
- // d[r][0] += d[i][0];
- // if(f[i][0])
- // f[r][0] = 1;
- // }
- // else{
- // d[r][0] += d[i][1];
- // if(d[i][1] == d[i][0] || f[i][1])
- // f[r][0] = 1;
- // }
- //// d[r][1] += d[i][0]; //如果选择了r这其下级不能选择
- //// if(!f[i][0]){
- //// flag = 0;
- //// }
- //// if(d[i][0] == d[i][1]){
- //// f[i][0] = 0;
- //// d[r][0] += d[i][0];
- //// }
- //// else if(d[i][0] > d[i][1]){
- //// d[r][0] += d[i][0];
- //// if(!f[i][0]){
- //// f[r][0] = 0;
- //// }
- //// }
- //// else{
- //// d[r][0] += d[i][1];
- //// if(!f[i][1]){
- //// f[r][0] = 0;
- //// }
- //// }
- //
- // }
- // }
- // if(flag){
- // f[r][1] = 1;
- }
- return;
- }
- int main(){
- #ifndef ONLINE_JUDGE
- freopen("inpt.txt","r",stdin);
- // freopen("output.txt","w",stdout);
- #endif
- while(~scanf("%d",&n) && n){
- cnt = ;
- memset(child,,sizeof(child));
- memset(f,,sizeof(f));
- memset(d,,sizeof(d));
- string str1;
- string str2;
- m.clear();
- cin >> str1;
- m[str1] = cnt++;
- int a,b;
- for(int i = ;i <= n;i++){
- G[i].clear();
- }
- for(int i = ;i < n;i++){
- cin >> str1 >> str2;
- a = getNum(str1);
- b = getNum(str2);
- G[b].push_back(a);
- }
- dp();
- if(d[][] == d[][]){
- printf("%d No\n",d[][]);
- }
- else if(d[][] > d[][]){
- printf("%d %s\n",d[][],!f[][]?"Yes":"No");
- }
- else{
- printf("%d %s\n",d[][],!f[][]?"Yes":"No");
- }
- }
- return ;
- }
poj 3398 Perfect Service / uva 1218
联通的计算机,从中间抽取几台电脑充当服务器,使每台电脑恰好有一台服务器相连,求最小的服务器数目
d(u,0) u是服务器,其子节点既可以是服务器,也可以不是服务器
d(u,1) u 不是服务器,但是其父亲是服务器,其儿子一定不是服务器
d(u,2) u不是服务器,其父亲也不是服务器,u恰好一个v是服务器
d(u,0) = sum{min(d(v,0),d(v,1)) } + 1;
d(u,1) = sum{d(v,2)};
d(u,2) = sum{d(vv,2)} = min(d(u,1)- d(v,2) + d(v,0)) //其某一个子节点为服务器
因为是无向树所以需要vis标记
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <cmath>
- #include <cstdlib>
- #include <cctype>
- #include <algorithm>
- #include <vector>
- const int MAXN = + ;
- const int INF = 0xffffff;
- const int mod = ;
- const double Pi = atan(1.0)*;
- const double ESP = 10e-;
- using namespace std;
- vector<int>G[MAXN];
- int d[MAXN][];
- bool vis[MAXN];
- int n;
- void dp(int u){
- vis[u] = ;
- int len = G[u].size();
- d[u][] = ; //u是服务器,其子节点既可以是服务器,也可以不是,其父节点可以是服务器,也可以不是
- d[u][] = ; //u不是服务器,但是u父亲是服务器,所以其子节点都不是服务器
- d[u][] = INF; // u,和u的父亲都不是服务器,所以u的子节点必须有点是服务器
- vector<int>arr;
- for(int i = ;i < len;i++){
- int v = G[u][i];
- if(vis[v])
- continue;
- dp(v);
- arr.push_back(v);
- d[u][] += min(d[v][],d[v][]); // 子节点既可以是服务器又可以不是服务器所以取最小值
- d[u][] += d[v][]; // u不是服务器,子节点不是服务器,所以等于d[v][2]父亲和其本身都不是服务器的相加
- }
- len = arr.size();
- for(int i = ;i < len;i++){
- int v = arr[i];
- d[u][] = min(d[u][],d[u][] - d[v][] + d[v][]);
- }
- }
- int main(){
- // freopen("input.txt","r",stdin);
- while(~scanf("%d",&n)){
- for(int i = ;i <= n;i++){
- G[i].clear();
- }
- memset(vis,,sizeof(vis));
- memset(d,,sizeof(d));
- for(int i = ;i < n;i++){
- int a,b;
- scanf("%d%d",&a,&b);
- G[b].push_back(a);
- G[a].push_back(b);
- }
- dp();
- int ans = INF;
- ans = min(d[][],d[][]);
- printf("%d\n",ans);
- scanf("%d",&n);
- if(n < )
- break;
- }
- return ;
- }
树状DP的更多相关文章
- 树状DP (poj 2342)
题目:Anniversary party 题意:给出N各节点的快乐指数,以及父子关系,求最大快乐指数和(没人职员愿意跟直接上司一起玩): 思路:从底向上的树状DP: 第一种情况:第i个员工不参与,F[ ...
- poj3659树状DP
Cell Phone Network Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6273 Accepted: 225 ...
- hdu 1561 The more, The Better_树状dp
题目链接 题意:给你一棵树,各个节点都有价值(除根节点),从根节点出发,选择m个节点,问最多的价值是多小. 思路:很明显是树状dp,遍历树时背包最优价值,dp[i][k]=max{dp[i][r]+d ...
- poj 2342 Anniversary party_经典树状dp
题意:Ural大学有n个职员,1~N编号,他们有从属关系,就是说他们关系就像一棵树,父节点就是子节点的直接上司,每个职员有一个快乐指数,现在要开会,职员和职员的直接上司不能同时开会,问怎才能使开会的快 ...
- 树状DP HDU1520 Anniversary party
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 题意:职员之间有上下级关系,每个职员有自己的happy值,越高在派对上就越能炒热气氛.但是必须是 ...
- [Codeforces743D][luogu CF743D]Chloe and pleasant prizes[树状DP入门][毒瘤数据]
这个题的数据真的很毒瘤,身为一个交了8遍的蒟蒻的呐喊(嘤嘤嘤) 个人认为作为一个树状DP的入门题十分合适,同时建议做完这个题之后再去做一下这个题 选课 同时在这里挂一个选取节点型树形DP的状态转移方程 ...
- HDU 4714 Tree2cycle(树状DP)(2013 ACM/ICPC Asia Regional Online ―― Warmup)
Description A tree with N nodes and N-1 edges is given. To connect or disconnect one edge, we need 1 ...
- poj2486--Apple Tree(树状dp)
Apple Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7789 Accepted: 2606 Descri ...
- 洛谷P2015 二叉苹果树(树状dp)
题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来 ...
- 洛谷P1122 最大子树和 (树状dp)
题目描述 小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题.于是当日课后,小明 ...
随机推荐
- 关于FTP操作的功能类
自己在用的FTP类,实现了检查FTP链接以及返回FTP没有反应的情况. public delegate void ShowError(string content, string title); // ...
- C#_会员管理系统:开发五(用户注册)
创建一个新的用户注册窗体(VIPRegistration.cs): 用户注册窗体(VIPRegistration.cs)详细代码如下: using System; using System.Colle ...
- BZOJ 3236: [Ahoi2013]作业( 莫队 + BIT )
莫队..用两个树状数组计算.时间复杂度应该是O(N1.5logN). 估计我是写残了...跑得很慢... ----------------------------------------------- ...
- HDU 3925 Substring 【大数相减】
题目意思是,给你提供两个数字 a 和 b a 可以不断的往上加, 直到b 为其子串 问的是 a 最小加几? 显而易见,a 的数据范围给了10 ^100非常大,直接模拟肯定不行 那么就用 b 减去 a ...
- IE6/7/8 CSS兼容性问题和解决方法汇总
断断续续的在开发过程中收集了好多的bug以及其解决的办法,都在这个文章里面记录下来了!希望以后解决类似问题的时候能够快速解决,也希望大家能在留言里面跟进自己发现的ie6 7 8bug和解决办法! 1: ...
- 使用MongoDB的开源项目(转)
根据谷歌的搜索结果筛选出来的. 统计应用 counlty https://count.ly/ mongopress 开源CMS系统 http://www.mongopress.org/ Rubedo ...
- BZOJ 2429: [HAOI2006]聪明的猴子( MST )
水题, 求MST即可. -------------------------------------------------------------------------------- #includ ...
- javascript每日一练(十三)——运动实例
一.图片放大缩小 <!doctype html> <html> <head> <meta charset="utf-8"> < ...
- C-整数划分
将正整数 n 表示成一系列正整数之和, n=n1+n2+…+nk, 其中 n1>=n2>=…>=nk>=1 , k>=1 . 正整数 n 的这种表示称为正整数 n 的划分 ...
- Git 将本次修改追加在上一次修改上面
Git 将本次修改追加在上一次修改上面 git add . git commit --amend 之后就是进入日志提交页面 确保change-Id那条记录出现在最后一行,如: zh-->en 修 ...