暑假集训 || 树DP
树上DP通常用到dfs https://www.cnblogs.com/mhpp/p/6628548.html
POJ 2342
相邻两点不能同时被选 经典题
f[0][u]表示不选u的情况数,此时v可选可不选
f[1][u]表示选u的情况数,此时v不选
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int SZ = ;
const int INF = 1e9+;
int f[][SZ];
int head[SZ], nxt[SZ], l[SZ], tot = ;
void build(int f, int t)
{
l[++tot] = t;
nxt[tot] = head[f];
head[f] = tot;
}
void dfs(int u, int fa)
{
for(int i = head[u];i;i = nxt[i])
{
int v = l[i];
if(v == fa) continue;
dfs(v, u);
f[][u] += max(f[][v], f[][v]);
f[][u] += f[][v];
}
return;
}
int main()
{
int n;
scanf("%d", &n);
for(int i = ; i <= n; i++) scanf("%d", &f[][i]);
while()
{
int u, v;
scanf("%d %d", &u, &v);
if(u == && v == ) break;
build(u, v);
build(v, u);
}
dfs(, );
printf("%d\n", max(f[][], f[][]));
return ;
}
URAL 1018
一个二叉树,每条边上都有一定的苹果,减去一些边使得剩下的苹果最多(要从叶子那儿开始剪
f[p][u]表示在u点及它的子树内一共选择p个点,能剩下的最多苹果数
边权不好处理,把它转移到点上
转移时考虑u点(根节点)一定选,在左儿子和右儿子中一共选p-1个,分别枚举即可
记忆化搜索,每次dfs时若这个f[p][u]之前已经算过,可以直接return这个值
struct Tree
{
int lc, rc;
}tree[SZ];
queue<int> q;
int vis[SZ], hasc[SZ];
void bfs()
{
q.push();
vis[] = ;
while(q.size())
{
int u = q.front(); q.pop();
int flag = ;
for(int i = head[u];i;i = nxt[i])
{
int v = l[i].t;
hasc[u] = ;
if(!vis[v])
{
vis[v] = ;
a[v] = l[i].d;
q.push(v);
if(!flag) tree[u].lc = v;
if(flag) tree[u].rc = v;
flag++;
}
}
}
return;
} int dfs(int u, int p)//以u为根的子树,保留p个点
{
if(p == ) return ;
if(f[p][u] > ) return f[p][u];
if(!hasc[u]) return a[u];
for(int i = ; i < p; i++)
{
f[p][u] = max(f[p][u], dfs(tree[u].lc, i) + dfs(tree[u].rc, p-i-) + a[u]);
}
return f[p][u];
}
int main()
{
scanf("%d %d", &n, &Q);
for(int i = ; i < n-; i++)
{
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
build(u, v, w);
build(v, u, w);
}
bfs();
printf("%d\n", dfs(, Q+));
return ;
}
最小支配集 && 最小点覆盖 && 最大独立集
https://www.cnblogs.com/Ash-ly/p/5783877.html
UVA 1218
选一些点,当一个点被选择的时候,它邻接的点就被覆盖了,要求每个点被覆盖有且仅有一次,问最少选多少个点
最小支配集
https://blog.csdn.net/wyjwyl/article/details/51447427
神奇。。。
const int SZ = ;
const int INF = 1e9+;
int f[][SZ];
int head[SZ], nxt[SZ], l[SZ], tot = ;
void build(int f, int t)
{
l[++tot] = t;
nxt[tot] = head[f];
head[f] = tot;
}
/*
f[0][u] u选了
f[1][u] u不选,有一个v选了
f[2][u] u不选,v不选
*/
void dfs(int u, int fa)
{
int sum = , inc = INF;
bool flag = false;
for(int i = head[u]; i; i = nxt[i])
{
int v = l[i];
if(v == fa) continue;
dfs(v, u);
f[][u] += (min(f[][v], f[][v]));
if(f[][v] <= f[][v])
{
sum += f[][v];
flag = true;
}
else
{
sum += f[][v];
inc = min(inc, f[][v] - f[][v]);
}
if(f[][v] != INF && f[][u] != INF) f[][u] += f[][v];
else f[][u] = INF;//
}
if(inc == INF && !flag) f[][u] = INF;
else
{
f[][u] = sum;
if(!flag) f[][u] += inc;
}
return;
}
int main()
{
int n;
while()
{
scanf("%d", &n);
memset(f, , sizeof(f));
memset(head, , sizeof(head));
tot = ;
for(int i = ; i < n-; i++)
{
int u, v;
scanf("%d %d", &u, &v);
build(u, v);
build(v, u);
}
for(int i = ; i <= n; i++) f[][i] = , f[][i] = ;
dfs(, );
printf("%d\n", min(f[][], f[][]));
int tmp;
scanf("%d", &tmp);
if(tmp == -) break;
}
return ;
}
Codeforces 274B
题意:给一棵树,每个点都有权值,每次操作可以把含有1号点的子树所有点权+1或者-1,问最少操作多少次可以让所有点权值都为0
思路:把点1作为根,考虑树上DP,从叶子开始每个点都有sub或者add,表示在这个点要加或减多少
在每个点加减后会影响它的父亲节点,对父亲节点的影响可以取max(要求总的操作次数最少)
神奇的dfs嗯
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <queue>
#include <set>
#include <vector>
#include <string>
using namespace std;
typedef long long LL;
const int SZ = ;
LL v[SZ];
int head[SZ*], nxt[SZ*], l[SZ*], tot = ;
LL sub[SZ], add[SZ];
void build(int f, int t)
{
l[++tot] = t;
nxt[tot] = head[f];
head[f] = tot;
}
void dfs(int u, int fa)
{
for(int i = head[u];i;i = nxt[i])
{
int v = l[i];
if(v != fa)
{
dfs(v, u);
sub[u] = max(sub[u], sub[v]);
add[u] = max(add[u], add[v]);
}
}
v[u] = v[u] - sub[u] + add[u];
if(v[u] > ) sub[u] += v[u];
else add[u] -= v[u];
}
int main()
{
int n;
scanf("%d", &n);
for(int i = ; i < n-; i++)
{
int x, y;
scanf("%d %d", &x, &y);
build(x, y);
build(y, x);
}
for(int i = ; i <= n; i++)
scanf("%I64d", &v[i]);
dfs(, );
printf("%I64d\n", add[] + sub[]);
return ;
}
暑假集训 || 树DP的更多相关文章
- 暑假集训 || 区间DP
区间DP 经典石子合并问题V1 复杂度 On3 int a[SZ], sum[SZ], f[SZ][SZ]; int main() { int n; scanf("%d", ...
- [暑假集训--数位dp]LightOj1205 Palindromic Numbers
A palindromic number or numeral palindrome is a 'symmetrical' number like 16461 that remains the sam ...
- [暑假集训--数位dp]hdu3709 Balanced Number
A balanced number is a non-negative integer that can be balanced if a pivot is placed at some digit. ...
- [暑假集训--数位dp]hdu3555 Bomb
The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the ti ...
- [暑假集训--数位dp]hdu3652 B-number
A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- ...
- [暑假集训--数位dp]hdu2089 不要62
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer).杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍, ...
- 暑假集训 || 概率DP
Codeforces 148D 考虑状态转移..https://www.cnblogs.com/kuangbin/archive/2012/10/04/2711184.html题意:原来袋子里有w只白 ...
- 2018.8.17 2018暑假集训 关于dp的一些感想(以目前的知识水平)
学了这么长时间的dp似乎还是不怎么样 谨以此篇文字记录一年以来与dp斗智斗勇的各种经历 关于dp(也就是动态规划)似乎对于每个OIer来说都是一个永远的噩梦. 刚刚开始学dp的时候完全搞不明白(只是觉 ...
- [暑假集训--数位dp]hdu5787 K-wolf Number
Alice thinks an integer x is a K-wolf number, if every K adjacent digits in decimal representation o ...
随机推荐
- C++实现利用(前序和中序生成二叉树)以及(二叉树的镜像)
#include<iostream> #include<string.h> #include<stack> using namespace std; typedef ...
- Windows下findstr命令的使用
命令:findstr 参数解释 /b 如果位于行的开头则匹配模式. /e 如果位于行的末尾则匹配模式. /l 使用文字搜索字符串. /r ...
- rn滑动返回页面监听
开发rn的同学都已经知道这个问题很坑了,真的很难弄,网上的方法尝试过很多,返回的的时候回调,是用的最多的,最开始我也是用的这种方式,但是滑动返回的时候监听不到.并且用起来也比较麻烦,不但需要在当前页面 ...
- hihocoder 1584 Bounce(找规律)
传送门 题意 略 分析 我们观察几张图 发现菱形的边长为n-1和m-1的公约数 将图简化一下 接下来我们计算只经过一次的点,分成两类 1.与边相交 num1=x+y 2.未与边相交,在菱形内 num2 ...
- 51nod 1489 蜥蜴和地下室(dp)
传送门 题意 分析 dp[12][20][20][20]; // dp[a][b][c][d]第a个弓箭手面临第a-1.a.a+1个弓箭手的生命值分别为b.c.d的状态 转移巧妙,需注意 trick ...
- BFS+PRIM
转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1299324104 在一个y行 x列的迷宫中,有可行走的通路空格' ',不可行走的墙'#', ...
- 转载文章 -- 难搞的滚动事件(滚动默认,scrollTop)
关于取消默认事件 现今的 chrome 浏览器,为了实现丝滑顺畅地滑动,活动时间直接执行而不再检测默认事件,这使得无法用 e.preventDafult() 来阻止默认事件. 现在需要添加 {pass ...
- HDFS Java API
HDFS Java API 搭建Hadoop客户端与Java访问HDFS集群
- Codeforces 669D Little Artem and Dance (胡搞 + 脑洞)
题目链接: Codeforces 669D Little Artem and Dance 题目描述: 给一个从1到n的连续序列,有两种操作: 1:序列整体向后移动x个位置, 2:序列中相邻的奇偶位置互 ...
- git导出代码
1.快速查询 $git archive --format zip --output "./output.zip" master -0 ./output.zip 是生成的文件 mas ...