树形dp入门题目总结——树的重心和最大独立集
来源:互联网 发布:喀秋莎录屏软件7 编辑:程序博客网 时间:2024/06/05 22:58
树形dp入门题目总结——树的重心和最大独立集
- 树形dp入门题目总结树的重心和最大独立集
- 一 无根树转为有根树
- 工人的请愿书
- 二 树的重心
- Balancing Act
- 三 树的最大独立集
- Anniversary party
- Party at Hali-Bula
- 一 无根树转为有根树
一. 无根树转为有根树
输入n个节点的无根树的各条边,指定一个节点为根,将无根树转为有根树。
int fa[maxn]; //每个节点的父亲 vector<int> G[maxn];int dfs(int f) //无根树化为有根树 { int i; for(i=0; i<G[f].size(); i++) { if(fa[f] != G[f][i]){ fa[G[f][i]] = f; dfs(G[f][i]); } }}
初始时设置fa[1] = -1,调用dfs(1)即可。
工人的请愿书
uva12186 题目链接
一个老板,n个员工,老板编号为0,除了老板之外每个工人都有唯一的直属上司,现在工人要签署一项请愿书,每个工人只能交给其直属上司,上司的直属下属中不少于T%的人签字,他才会向上提交,问要让老板收到,至少需要多少工人签字。
思路:
d[i]表示i员工上交时最少需要多少人签字,访问i节点时,将其子节点值排序取前面T%人相加。
#include<iostream>#include<algorithm>#include<vector> #include<cmath>using namespace std;const int maxn = 100001;int n, t;vector<int> G[maxn];int d[maxn]; //d[i]表示i员工上交时最少需要多少人签字 void dfs(int k){ int i; vector<int> ans; for(i=0; i<G[k].size(); i++) { int v = G[k][i]; dfs(v); ans.push_back(d[v]); } d[k] = 0; if(G[k].size() == 0){ d[k] = 1; return; } sort(ans.begin(), ans.end()); for(i=0; i<ceil((double)t/100*G[k].size()); i++) { d[k] += ans[i]; }}int main(){ int i, j, k; while(1) { cin >> n >> t; if(n == 0 && t == 0){ break; } for(i=0; i<=n; i++){ G[i].clear(); } for(i=1; i<=n; i++) { int x; cin >> x; G[x].push_back(i); } dfs(0); cout << d[0] << endl; } return 0; }
二. 树的重心
对于一个无根树,找到一个节点,使以这个节点为根时其他子树的最大节点数最小。
Balancing Act
POJ1655 题目链接
Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1…N. Deleting any node from the tree yields a forest: a collection of one or more trees. Define the balance of a node to be the size of the largest tree in the forest T created by deleting that node from T.
Deleting node 4 yields two trees whose member nodes are {5} and {1,2,3,6,7}. The larger of these two trees has five nodes, thus the balance of node 4 is five. Deleting node 1 yields a forest of three trees of equal size: {2,6}, {3,7}, and {4,5}. Each of these trees has two nodes, so the balance of node 1 is two.
For each input tree, calculate the node that has the minimum balance. If multiple nodes have equal balance, output the one with the lowest number.
思路:
在无根树转为有根树过程中,对每个节点k求其以k为根的各个子树中的最大节点数maxx,和k这颗子树节点数总和num,k的实际子树的最大值为max(maxx, n - num);
#include<iostream>#include<vector>#include<algorithm>using namespace std;const int maxn = 20001;vector<int> G[maxn];int fa[maxn]; //每个节点的父亲 int node[maxn]; //每个节点的最大子树节点数 int n;int dfs(int f) //无根树化为有根树 { int i; int maxx = 0; int count = 1; for(i=0; i<G[f].size(); i++) { if(fa[f] != G[f][i]){ fa[G[f][i]] = f; int cur = dfs(G[f][i]); count += cur; if(cur > maxx){ maxx = cur; } } } node[f] = max(maxx, n - count); return count;}int main(){ int i, j, k; int t; cin >> t; for(k=1; k<=t; k++) { cin >> n; for(i=1; i<=n; i++){ G[i].clear(); fa[i] = 0; } for(i=1; i<n; i++) { int a, b; cin >> a >> b; G[a].push_back(b); G[b].push_back(a); } dfs(1); int minn = 999999999; int mini; for(i=1; i<=n; i++){ if(node[i] < minn){ minn = node[i]; mini = i; } } cout << mini << " " << minn << endl; }}
三. 树的最大独立集
对于一个n个节点的无根树,选出尽量多的节点,使得任意两个节点不相邻。
Anniversary party
hdu1520 题目链接
每个节点有权值,问选中的最大权值为多少
思路:
定义dp[i][0]为不选择i节点的最大权值,d[i][1]为选中i节点的最大权值。
状态转移方程:dp[i][0] = max(dp[j][0], dp[j][1])
dp[i][1] = dp[j][0] + value[i].
#include<stdio.h>#include<cstring>#include<vector>#include<iostream>using namespace std;int n;vector<int> v[6001];int dp[6001][2];int visit[6001];void dpp(int x){ if(visit[x] == 1){ return; } visit[x] = 1; int i; for(i=0; i<v[x].size(); i++) { dpp(v[x][i]); int t = v[x][i]; dp[x][0] += max(dp[t][0], dp[t][1]); dp[x][1] += dp[t][0]; }}int main(){ int n; int i; while(~scanf("%d", &n)) { for(i=0; i<6001; i++){ v[i].clear(); } memset(visit, 0, sizeof(visit)); memset(dp, 0, sizeof(dp)); for(i=1; i<=n; i++) { scanf("%d", &dp[i][1]); } while(1) { int a, b; scanf("%d%d", &a, &b); if(a == 0 && b == 0){ break; } v[b].push_back(a); } int maxx = 0; for(i=1; i<=n; i++) { dpp(i); if(maxx < dp[i][0]){ maxx = dp[i][0]; } if(maxx < dp[i][1]){ maxx = dp[i][1]; } } printf("%d\n", maxx); } return 0;}
Party at Hali-Bula
uva1220 题目链接
问最多选择多少人,且方案是否唯一
思路:
前一问相当于最大独立集问题,后一问判断唯一性
定义d[i][0]表示i节点不选最多选多少人,d[i][1]表示i节点选择最多选多少人 ,
f[i][0]表示i节点不选的方案是否唯一,f[i][1]表示i节点选择方案是否唯一 .
d数组的状态转移方程和前一题类似。
f[i][1] = 1当且仅当f[j][0] = 1,j节点为i节点子节点中任意一点,表示唯一,
f[i][0]时,每个子节点可选可不选,若选择和不选择的d值一样,则f[i][0]=0,表示不唯一,否则每个子节点最大d值得情况下,其f值来决定f[i][0]值,具体参考程序代码。
#include<iostream>#include<vector>#include<map>#include<string>using namespace std;const int maxn = 201;map<string, int> names;vector<int> G[maxn];int d[maxn][2]; //d[i][0]表示i节点不选最多选多少人,d[i][1]表示i节点选择最多选多少人 int f[maxn][2]; //f[i][0]表示i节点不选的方案是否唯一,f[i][1]表示i节点选择方案是否唯一 int n;void dfs(int k){ int i; d[k][1] = 1; f[k][1] = 1; d[k][0] = 0; f[k][0] = 1; for(i=0; i<G[k].size(); i++) { int v = G[k][i]; dfs(v); d[k][1] += d[v][0]; if(!f[v][0]){ f[k][1] = 0; } if(d[v][0] < d[v][1]){ d[k][0] += d[v][1]; if(!f[v][1]){ f[k][0] = 0; } } else{ d[k][0] += d[v][0]; if(!f[v][0]){ f[k][0] = 0; } if(d[v][0] == d[v][1]){ f[k][0] = 0; } } } }int main(){ int i, j, k; //freopen("tt.out", "w", stdout); while(1) { cin >> n; if(n == 0){ break; } for(i=0; i<=n; i++){ G[i].clear(); } i = 1; string str; cin >> str; names[str] = i; string str1[201][2]; for(i=2; i<=n; i++) { cin >> str1[i][0] >> str1[i][1]; names[str1[i][0]] = i; } for(i=2; i<=n; i++){ int u = names[str1[i][1]]; int v = names[str1[i][0]]; G[u].push_back(v); } dfs(1); if(d[1][0] < d[1][1]){ cout << d[1][1] << " "; cout << (f[1][1] ? "Yes" : "No") << endl; } else{ cout << d[1][0] << " "; if(d[1][0] == d[1][1]){ cout << "No" << endl; } else{ cout << (f[1][0] ? "Yes" : "No") << endl; } } } return 0;}
- 树形dp入门题目总结——树的重心和最大独立集
- 树的最大独立集——树形dp
- 树的重心——树形dp
- hdu 2412 基础树形DP 树的最大独立集
- poj1655Balancing Act 树的重心,树形dp
- 树形dp求树的重心 poj1655
- 树的重心 树形DP SGU 134
- God Father (树形dp 树的重心)
- POJ3107-树的重心&树形DP-Godfather
- 树的重心(树形DP)
- Godfather (树形dp,树的重心)
- Godfather (树形dp + 树的重心)
- ZJK的黑OJ(树的最大独立集)(树形DP)
- 树形dp 树的最小支配集,最小点覆盖与最大独立集
- POJ3342 Party at Hali-Bula(树的最大独立集-树形DP-刷表法)
- POJ 3342 Party at Hali-Bula (树形dp 树的最大独立集 判多解 好题)
- poj3342-Party at Hail-Bula 树形dp/树的最大独立集
- 树形DP+树的最大独立集+无根树转化有根树 模板
- its MIME type ('text/html') is not executable, and strict MIME type checking is enabled(非404)
- ssh框架被淘汰——上海第一手资讯(综合了我刚刚就业的的几位同学的感受)
- 【多视图几何】TUM 课程 第1章 数学基础:线性代数
- 微信小程序实战之天气预报
- php面向对象视频笔记之第一章(面向对象基础)
- 树形dp入门题目总结——树的重心和最大独立集
- 关于一瓶啤酒2元,4个瓶盖换1瓶,2个空瓶换1瓶,10元能喝多少瓶的问题求解
- spark生成json文件
- 串行数据记录仪——INI配置文件
- unity3d 2D物体的移动
- Map接口
- sicily 选择排序比较次数 期末测试
- 80x86工作模式
- 利用SecureCRT传送文件到RedHat