1.cf 804 C
最大团染色+dfs
题目中有个条件,相同的冰淇淋所在的节点是连通的,这个很重要
那么我们就对这个树T进行dfs,同时给G染色就行了
最大团染色xjb写
代码
2.xidian 1070
树形dp
dp[i][j]表示以i为根选j个节点的最大值
注意:类似于01背包那样逆推,就不会重复选择相同的子树了
代码
树形dp
1)暴力dfs
保存每一个顶点连同的顶点。
每一次输入v,d,c,搜索v节点的d范围内能够染色的点,每一次d-1;
然后你会发现完美的超时了
2)dp
dp[i][d]表示当前i节点d距离时的颜色,所以dp[i][0]为i节点的颜色,
所以就可以在dfs时判断如果当前节点dp[i][d]已经染了色,就可以不用染色了。
还有的就是:因为颜色是覆盖的,所以最后染的颜色就是结束的颜色。所以我们应该从后往前开始染色。
这样就可以保证,如果这节点d[i][0]染了色,就不会被覆盖了。
复杂度O(n*d)
代码
3)优化dfs
反过来做,染色过的点就不再染色
对于点u来说,如果以它为中心,距离为d的所有点都被染色过,那么下次你要对u距离为d’ (d’<=d) 的点染色时就可以直接退出了
复杂度O(n)
代码
4.poj1947
题意:
给一棵树,问最少删掉几条边.使得剩下的子树中有节点个数为p个。
思路:
正过来想删多少边不好想,可以反过来思考保留多少节点
f(i, j) 表示子树i,保留j个节点的最少删边次数, 注意,这里保留的j个节点的子树,是指根节点
为i的且有j个节点的子树.这样理解的话, 状态转移就容易想多了.
对于子树i, 如果只保留1个节点,那么连接它所有儿子节点的边都要删掉,
所以可以初始化 f(i, 1) = 节点i的儿子个数
f(i, j), 即子树i保留j个节点, 那么对于i的每个子树,可以选择保留1,2,..j-1个节点
那么每个子树可以看作是一组物品,对所有子树做分组背包
子树v选择保留k个点的话,那么子树i就要保留j-k个点.
所以由状态转移:
f(i, j) = max{ max{f(i,j-k) + f(v, k) - 1 | 1<=k<s} | v是i的儿子节点 }
最终ans = min{ f(i, p) | 1<=i<=n }