【POJ 1848】Tree【树形DP】
来源:互联网 发布:送女生生日礼物 知乎 编辑:程序博客网 时间:2024/05/16 15:20
题意:给定一棵树,要添加一些边,不能是重边,不能是自环,让它的每一个结点都恰好属于一个环,求最少添加的边数。
思路:树形DP, 定义dp[i][0]表示i为根的子树所满足条件的最优解,dp[i][1]表示以i为根的子树除了i节点外的点满足条件的最优解,dp[i][2]表示以i为根的子树,除了i节点以及它的一个直接孩子节点除外的点满足条件的最优解。
转移方程:dp[i][1] = ∑dp[k][0] (k为i的孩子节点),
dp[i][2] = (∑dp[k][0])-dp[j][0]+min(dp[j][1], dp[j][2]),
dp[i][0] = min(min((∑dp[k][0])-dp[j][0]+dp[j][2]+1), min((∑dp[k][0])-dp[j][0]-dp[h][0]+min(dp[j][1], dp[j][2])+min(dp[h][1], dp[h][2]))
第一个转移方程显然成立,第二个转移方程相当于在i的孩子中找到j使得i, j不在环中,也就是对于j为根的子树中,j不在环中所需要的边数最小值,也就是min(dp[j][1], dp[j][2])。
第三个转移方程,分为两种情况,在i的孩子中找到一个j并且使得j的一个孩子与j都不在换中,然后这三个点连成环,即min((∑dp[k][0])-dp[j][0]+dp[j][2]+1), 第二种情况就是寻找i的两个孩子,使得这三个点在同一个环中,也就是后面的式子了。
思路:树形DP, 定义dp[i][0]表示i为根的子树所满足条件的最优解,dp[i][1]表示以i为根的子树除了i节点外的点满足条件的最优解,dp[i][2]表示以i为根的子树,除了i节点以及它的一个直接孩子节点除外的点满足条件的最优解。
转移方程:dp[i][1] = ∑dp[k][0] (k为i的孩子节点),
dp[i][2] = (∑dp[k][0])-dp[j][0]+min(dp[j][1], dp[j][2]),
dp[i][0] = min(min((∑dp[k][0])-dp[j][0]+dp[j][2]+1), min((∑dp[k][0])-dp[j][0]-dp[h][0]+min(dp[j][1], dp[j][2])+min(dp[h][1], dp[h][2]))
第一个转移方程显然成立,第二个转移方程相当于在i的孩子中找到j使得i, j不在环中,也就是对于j为根的子树中,j不在环中所需要的边数最小值,也就是min(dp[j][1], dp[j][2])。
第三个转移方程,分为两种情况,在i的孩子中找到一个j并且使得j的一个孩子与j都不在换中,然后这三个点连成环,即min((∑dp[k][0])-dp[j][0]+dp[j][2]+1), 第二种情况就是寻找i的两个孩子,使得这三个点在同一个环中,也就是后面的式子了。
#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;#define N 110#define inf 10000vector<int>V[N];int dp[N][3];void dfs(int u, int f) { int i, j, v, sum = 0; vector<int>sun; for (i = 0;i < V[u].size();i++) { v = V[u][i]; if (v == f) continue; dfs(v, u); sun.push_back(v); sum += dp[v][0]; } if (sun.size() == 0) { dp[u][1] = 0, dp[u][0] = inf, dp[u][2] = inf; return; } dp[u][1] = sum; int t1, t2; t2 = t1 = inf; for (i = 0;i < sun.size();i++) { v = sun[i]; t2 = min(t2, sum-dp[v][0]+min(dp[v][1], dp[v][2])); t1 = min(t1, sum-dp[v][0]+dp[v][2]+1); for (j = i+1;j < sun.size();j++) { int vv = sun[j]; t1 = min(t1, sum-dp[v][0]-dp[vv][0]+1+min(dp[v][1],dp[v][2])+min(dp[vv][1], dp[vv][2])); } } dp[u][0] = t1, dp[u][2] = t2;}int main() { int n, i, j, u, v; while (~scanf("%d", &n)) { for (i = 1;i <= n;i++) V[i].clear(); for (i = 1;i < n;i++) { scanf("%d%d", &u, &v); V[u].push_back(v), V[v].push_back(u); } dfs(1, -1); if (dp[1][0] >= inf) puts("-1"); else printf("%d\n", dp[1][0]); }}
0 0
- 【POJ 1848】Tree【树形DP】
- poj 1848 Tree 树形dp
- POJ 1848 Tree 树形DP
- poj 1848 Tree 树形dp
- POJ Apple Tree 树形dp
- POJ 1848树形DP
- POJ 2486 Apple Tree 树形DP
- POJ 2486 Apple Tree 树形dp
- POJ--2378--Tree Cutting--树形DP
- POJ--2486--Apple Tree--树形回溯DP
- 【树形DP】 POJ 2486 Apple Tree
- poj 2378 Tree Cutting(树形dp)
- poj 2486 Apple Tree(经典树形DP)
- poj 1741 Tree(树形DP+分治)难
- poj 2486 Apple Tree 树形dp
- *(中等) 树形dp POJ 2486 Apple Tree
- (简单) 树形dp POJ 2378 Tree Cutting
- poj 2486 Apple Tree (树形dp)
- webrtc开源项目音频重采样“不友好接口”的几点总结
- 黑马程序员 快速入门java
- java提高篇(一) java知识汇总-------io流知识汇总(io学习流程)
- 115_屏幕适配,dip与px互相转换
- 3.1.3、为AutoCAD程序实现入口点函数
- 【POJ 1848】Tree【树形DP】
- 二分图基本概念
- 图解EM算法
- java提高篇(一)拓展篇 java知识汇总---IO流的使用规律总结(含代码示例)浅显易懂
- dSYM 文件的作用
- JAVA实现冒泡排序算法
- markdown
- VS2010 项目属性页配置
- HDU2444 The Accomodation of Students(染色法判断二分图+最大匹配)