树上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的更多相关文章

  1. 暑假集训 || 区间DP

    区间DP 经典石子合并问题V1    复杂度 On3 int a[SZ], sum[SZ], f[SZ][SZ]; int main() { int n; scanf("%d", ...

  2. [暑假集训--数位dp]LightOj1205 Palindromic Numbers

    A palindromic number or numeral palindrome is a 'symmetrical' number like 16461 that remains the sam ...

  3. [暑假集训--数位dp]hdu3709 Balanced Number

    A balanced number is a non-negative integer that can be balanced if a pivot is placed at some digit. ...

  4. [暑假集训--数位dp]hdu3555 Bomb

    The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the ti ...

  5. [暑假集训--数位dp]hdu3652 B-number

    A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- ...

  6. [暑假集训--数位dp]hdu2089 不要62

    杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer).杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍, ...

  7. 暑假集训 || 概率DP

    Codeforces 148D 考虑状态转移..https://www.cnblogs.com/kuangbin/archive/2012/10/04/2711184.html题意:原来袋子里有w只白 ...

  8. 2018.8.17 2018暑假集训 关于dp的一些感想(以目前的知识水平)

    学了这么长时间的dp似乎还是不怎么样 谨以此篇文字记录一年以来与dp斗智斗勇的各种经历 关于dp(也就是动态规划)似乎对于每个OIer来说都是一个永远的噩梦. 刚刚开始学dp的时候完全搞不明白(只是觉 ...

  9. [暑假集训--数位dp]hdu5787 K-wolf Number

    Alice thinks an integer x is a K-wolf number, if every K adjacent digits in decimal representation o ...

随机推荐

  1. k8s-网络插件flannel-十八

    一.kubernetes的网络模式  (1)Kubernetes网络需要解决的问题 集群内: 容器与容器之间的通信 Pod和Pod之间的通信 Pod和服务之间的通信 集群外: 外部应用与服务之间的通信 ...

  2. HDOJ3231醉

    反正一开始就是瞎几把看题,然后题意理解了,什么飞机?只能去看题解了. 呵呵,可惜,题解看了三个小时,还是一知半解,先写了. - -菜鸡超级详细题解,强行掰弯一波,等下再问问别人吧. OK,OK开始!! ...

  3. SVG如何嵌套在HTML中

    1.使用HTML标签 以下三个标签所有主流浏览器都支持 a.<iframe>标签 优势:允许使用脚本 缺点:虽然不是HTML5的新增标签,但是不推荐在HTML4 和 XHTML中使用 例: ...

  4. IDEA thymeleaf ${xxx.xxx}表达式报错,红色波浪线

    解决方法: 在<!DOCTYPE html>标签下面加上 <!--suppress ALL--> 代码如图: 不再报错,效果如下图:

  5. Luogu P4139 上帝与集合的正确用法【扩展欧拉定理】By cellur925

    题目传送门 题目中的式子很符合扩展欧拉定理的样子.(如果你还不知扩展欧拉定理,戳).对于那一堆糟心的2,我们只需要递归即可,递归边界是模数为1. 另外,本题中好像必须要用快速乘的样子...否则无法通过 ...

  6. python 列表 元组

    1.列表的基本声明和赋值 #声明一个空列表 变量 = [] 或者 变量 = list() var = [1] var2 = list() # 声明带有数据的列表 var = [1,2,3,'一','二 ...

  7. Party Games UVA - 1610

    题目 #include<iostream> #include<string> #include<algorithm> using namespace std; // ...

  8. curry柯里化函数实现

    curry柯里化函数实现 参考文章: 一行写出javascript函数式编程中的curry 感谢作者分享 第一步: 缓存原始函数的参数个数 function curry(fn) { var limit ...

  9. 482 License Key Formatting 注册码格式化

    详见:https://leetcode.com/problems/license-key-formatting/description/ C++: class Solution { public: s ...

  10. [在读]javascript框架设计

    司徒正美的书,内容我觉得不错,国内的书很少会讲这些.当然也有很多人吐槽它只贴代码没有解释,文笔不够优美啥啥的,我想说,不要在意这些细节,反正是值得买的一本.