[LA 6745 Traitor] 树上覆盖DP
来源:互联网 发布:中央电视台网络春晚 编辑:程序博客网 时间:2024/04/29 17:18
题目
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=607&page=show_problem&problem=4757
分析
经典树上覆盖DP
设f[i][0]表示以i为根的子树,i不被儿子覆盖,也不覆盖儿子的最大值
设f[i][1]表示以i为根的子树,i被儿子覆盖,但是不覆盖儿子的最大值
设f[i][2]表示以i为根的子树,i不被儿子覆盖,但是覆盖儿子的最大值
设f[i][3]表示以i为根的子树,i被儿子覆盖,同时也覆盖儿子的最大值
那么
f[i][0]=sigma{max{f[j][0],f[j][1],f[j][2],f[j][3]}},j是i的儿子
f[i][1]=max{sigma{max{f[j][0],f[j][1],f[j][2],f[j][3]}}+max{f[k][0],f[k][1]}+tag[i]},k是i的某个儿子,j是i除k以外的儿子
f[i][2]=max{sigma{max{f[j][0],f[j][1],f[j][2],f[j][3]}}+max{f[k][0],f[k][2]}+tag[k]},k是i的某个儿子,j是i除k以外的儿子
f[i][3]=max{sigma{max{f[j][0],f[j][1],f[j][2],f[j][3]}}+max{f[p][0],f[p][1]}+tag[i]+max{f[q][0],f[q][2]}+tag[q]},p和q是i的某个儿子,j是i除p和q以外的儿子
对于3的转移,用一个状压DP实现
时间复杂度O(N)
代码
/************************************************** * Problem: LA 6745 * Author: clavichord93 * State: Accepted **************************************************/#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;const int MAX_N = 10005;const int MAX_E = 10005;struct Edge { int dest; Edge *next; Edge() {} Edge(int _dest, Edge *_next) : dest(_dest), next(_next) {}};Edge EdgePool[MAX_E];Edge *EP;Edge *e[MAX_N];int n, m;int parent[MAX_N];int tag[MAX_N];int f[MAX_N][4];int g[MAX_N];int h[4];inline void addedge(int a, int b) { e[a] = new(EP++)Edge(b, e[a]);}void dp(int i) { for (Edge *j = e[i]; j; j = j->next) { dp(j->dest); } int sum = 0; for (Edge *j = e[i]; j; j = j->next) { sum += g[j->dest]; } f[i][0] = sum; f[i][1] = f[i][2] = f[i][3] = 0; h[0] = h[1] = h[2] = h[3] = 0; for (Edge *j = e[i]; j; j = j->next) { f[i][1] = max(f[i][1], sum - g[j->dest] + max(f[j->dest][0], f[j->dest][1]) + tag[i]); f[i][2] = max(f[i][2], sum - g[j->dest] + max(f[j->dest][0], f[j->dest][2]) + tag[j->dest]); h[3] += g[j->dest]; h[3] = max(h[3], h[2] + max(f[j->dest][0], f[j->dest][1]) + tag[i]); h[3] = max(h[3], h[1] + max(f[j->dest][0], f[j->dest][2]) + tag[j->dest]); h[2] += g[j->dest]; h[2] = max(h[2], h[0] + max(f[j->dest][0], f[j->dest][2]) + tag[j->dest]); h[1] += g[j->dest]; h[1] = max(h[1], h[0] + max(f[j->dest][0], f[j->dest][1]) + tag[i]); h[0] += g[j->dest]; } f[i][3] = h[3]; g[i] = max(max(f[i][0], f[i][1]), max(f[i][2], f[i][3]));}int main() { #ifdef LOCAL_JUDGE freopen("in.txt", "r", stdin); #endif while (scanf("%d %d", &n, &m), n || m) { EP = EdgePool; memset(e, 0, sizeof(e)); memset(f, 0, sizeof(f)); memset(g, 0, sizeof(g)); memset(tag, 0, sizeof(tag)); for (int i = 1; i <= n; i++) { scanf("%d", &parent[i]); if (parent[i]) { addedge(parent[i], i); } } for (int i = 1; i <= m; i++) { int x; scanf("%d", &x); tag[x] = 1; } int ans = 0; for (int i = 1; i <= n; i++) { if (parent[i] == 0) { dp(i); ans += g[i]; } } printf("%d\n", ans); } return 0;}
- [LA 6745 Traitor] 树上覆盖DP
- LA 3942 Remember the Word(前缀树&树上DP)
- LA 3942 Remember the Word(字典树/树上dp)
- 单词拆解&前缀树&树上DP LA 3942 Remember the Word
- UVA1292-----Strategic game-----树形DP解决树上的最小点覆盖问题
- POJ 1463 Strategic game(树形DP-树上的点集覆盖模型)
- LA 2038 Strategic game(二分图最小顶点覆盖 /树形DP)
- hdu_1054最小点覆盖树上
- HDU2196--------树上DP
- HDU2196--------树上DP
- hdu4035 树上概率dp
- 树形dp--树上涂色
- 树上的DP
- 树DP 树上染色
- HDU6201(树上dp)
- hdu5956 树上斜率DP
- 树上的 DP
- LA 2678 Meteor (区间覆盖)
- Shell编程之函数返回值
- web service 学习笔记
- Errors running builder 'Android Pre Compiler' on project 'CriminalIntent'. java.lang.NullPointerExce
- locate命令的使用
- 小白学c++之模板类
- [LA 6745 Traitor] 树上覆盖DP
- 水数论HDU 2973
- hdu 3999The order of a Tree
- ovirt-智能卡设备
- 学习C++:实践者的方法(Beta1)
- vim user-manual第二章小节
- poj 1151Atlantis线段树+扫面线
- Android开发——通过使用getResource.getIdentifier() 获取layout中组件id
- hdu 5030 Rabbit's String sa+rmq+二分