树形dp基础题
来源:互联网 发布:小米id解锁软件 编辑:程序博客网 时间:2024/06/16 11:47
树形dp理解
该dp的实质就是利用树的性质,儿子节点返回的值可以被父亲节点加以利用以及处理,这样就构成了一种在树结构上的动态规划,简称树形dp。从昨天开始决定刷树形dp专题,刷了4道水题,因此想写一个博客总结一下。
POJ 1463 Strategic game
这道题就是在树上的节点添加守卫,很明显我们可以得出以下结论,如果父亲节点不添加守卫,那么儿子节点一定要添加守卫,如果父亲节点添加了守卫,那么儿子节点可以选择添加或者不添加守卫。即:
dp[fa][0]+=dp[son][1];dp[fa][1]+=min(dp[son][1],dp[son][0]);
这里我用数组的第二维表示添加守卫还是没有添加守卫,0表示没有添加,1表示添加了守卫。给出AC代码:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 1505;int tot;int head[maxn],dp[maxn][3],vis[maxn];struct Edge{ int to,next;}e[maxn<<1];void addedge(int from, int to){ e[tot].to = to; e[tot].next = head[from]; head[from] = tot++;}void dfs(int u){ vis[u] = 1; dp[u][0] = 0; dp[u][1] = 1; for(int i = head[u]; i != -1; i = e[i].next){ int v = e[i].to; if(!vis[v]){ dfs(v); dp[u][0] += dp[v][1]; dp[u][1] += min(dp[v][1], dp[v][0]); } }}int main(){ int n,m; while(scanf("%d", &m) != EOF){ int from, to; tot = 0; memset(head, -1, sizeof(head)); memset(vis, 0, sizeof(vis)); while(m--){ scanf("%d:(%d)", &from, &n); while(n--){ scanf("%d", &to); addedge(from, to); addedge(to, from); } } dfs(0); printf("%d\n", min(dp[0][0], dp[0][1])); } return 0;}
POJ 2378 Tree Cutting
这道题就是简单的dfs,感觉没有用到什么dp的思想,判断儿子节点数有没有超过总结点数的一半,判断除去以该点为根的子树节点数剩下的节点有没有超过总结点数的一半,这样很容易得出结论。
#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 10005;struct Edge{ int to,next;}e[maxn<<1];int N,siz[maxn],head[maxn],vis[maxn],half,ok[maxn],tot;vector <int> vec;void addedge(int from,int to){ e[tot].to = to; e[tot].next = head[from]; head[from] = tot++;}void dfs(int now){ siz[now] = 1; vis[now] = 1; for(int u = head[now]; u != -1; u = e[u].next){ int v = e[u].to; if(!vis[v]){ dfs(v); if(siz[v] > half) ok[now] = 1; siz[now] += siz[v]; } } if(N - siz[now] > half) ok[now] = 1;}int main(){ while(scanf("%d", &N) != EOF){ int from,to; tot = 0; memset(head, -1, sizeof(head)); memset(vis, 0, sizeof(vis)); memset(ok, 0, sizeof(ok)); memset(siz, 0, sizeof(siz)); for(int i = 1; i < N; i++){ scanf("%d%d", &from, &to); addedge(from, to); addedge(to, from); } half = N/2; dfs(1); for(int i = 1; i <= N; i++){ if(!ok[i]) printf("%d\n", i); } } return 0;}
POJ 3140 Contestants Division
与上题基本无差别。但是注意要用long long,并且abs函数要重写,因为long long类型不支持math.h中的abs
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;const int maxn = 100005;const int maxm = 1000005;const LL INF = 0x3f3f3f3f3f3f3f3f;struct Edge{ int to,next;}e[maxm<<1];int head[maxn],vis[maxn],tot;LL MIN,total,val[maxn];LL Abs(LL a,LL b){ if(a > b) return a-b; else return b-a;}void addedge(int from, int to){ e[tot].to = to; e[tot].next = head[from]; head[from] = tot++;}void dfs(int u){ vis[u] = 1; for(int i = head[u]; i != -1; i = e[i].next){ int v = e[i].to; if(!vis[v]){ dfs(v); val[u] += val[v]; } } LL temp = Abs(val[u], total-val[u]); MIN = min(MIN, temp);}int main(){ int N,M,kase = 1; while(scanf("%d%d", &N, &M) != EOF){ if(!M && !N) break; total = 0; for(int i = 1; i <= N; i++){ scanf("%I64d", &val[i]); total += val[i]; } int from,to; tot = 0; memset(head, -1, sizeof(head)); memset(vis, 0, sizeof(vis)); for(int i = 1; i <= M; i++){ scanf("%d%d", &from, &to); addedge(from, to); addedge(to, from); } MIN = INF; dfs(1); printf("Case %d: %I64d\n", kase++, MIN); } return 0;}
SGU 134 Centroid
这道题不想提了,sb题,找了半天bug,多组数据还不给过,写的一头包。
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 16005;const int INF = 0x3f3f3f3f;int head[maxn],vis[maxn],son[maxn],siz[maxn],vec[maxn],tot,N;struct Edge{ int to,next;}e[maxn<<1];void addedge(int from,int to){ e[tot].to = to; e[tot].next = head[from]; head[from] = tot++;}void dfs(int u){ vis[u] = 1; siz[u] = 1; for(int i = head[u]; i != -1; i = e[i].next){ int v = e[i].to; if(!vis[v]){ dfs(v); siz[u] += siz[v]; if(son[u] < siz[v]) son[u] = siz[v]; } } son[u] = max(son[u], N-siz[u]);}int main(){ scanf("%d", &N); int from,to; memset(head, -1, sizeof(head)); memset(vis, 0, sizeof(vis)); memset(siz, 0, sizeof(siz)); memset(son, 0, sizeof(son)); memset(vec, 0, sizeof(vec)); tot = 0; for(int i = 1; i < N; i++){ scanf("%d%d", &from, &to); addedge(from, to); addedge(to, from); } dfs(1); int ans = INF,len = 0; for(int i = 1; i <= N; i++){ if(son[i] < ans){ len = 0; vec[len++] = i; ans = son[i]; } else if(son[i] == ans) vec[len++] = i; } printf("%d %d\n",ans,len); for(int i = 0; i < len; i++) if(i != len-1) printf("%d ", vec[i]); else printf("%d\n", vec[i]); return 0;}
0 0
- 树形dp基础题
- uvalive2038(树形DP基础题)
- hdu1520 Anniversary party(树形dp基础题)
- Anniversary party(树形dp 基础题)
- 基础树形DP小结
- uva1220(基础树形dp)
- uva1292(基础树形dp)
- poj 2342 Anniversary party(树形DP基础题)(树形dp模板)
- SGU134 Centroid 树形DP基础题,求树的重心
- zoj 3201 Tree of Tree 树形dp基础题——树形背包
- 树形DP经典题
- HDU 5326 Work (基础树形dp)
- hdu1250Anniversary party 树形dp入门基础
- Fzu 2256 迷宫【基础树形Dp】
- 树形背包基础题
- 几道树形DP题
- 树形dp入门6题
- hdu 1054 Strategic Game 树形dp基础题,树的最小点覆盖
- android 后台服务、通知信息
- TSP问题(状压DP+Floyd解决方式)
- js遍历/迭代数组
- Android实现Facebook第三方分享
- stardic字典库下载 --批量解压缩和转移
- 树形dp基础题
- UICollectionView 设置头标题和头标题的高度
- 【Java学习】Java IO-File类的理解和总结
- 常见的几种RuntimeException
- jQuery Ajax 实例 ($.ajax、$.post、$.get)
- springmvc_mybatis3
- 用js使得输入框input只能输入数字
- Android 开发Emoji 适配IOS
- 【最长递增子序列+(不下降)二分栈】Educational Codeforces Round 15