题意:给一棵树,删边和加边的代价都为1,求把树变成一个圈所花的最小代价。

思路:对原树进行删边操作,直到将原树分成若干条链,然后通过在链之间添加边形成圈,由于删边和加边一一对应,且最后需要额外一条边连成圈,所以有:

最小代价=(最小链数-1)*2+1=最小链数*2-1。

令dp[i][0]表示i不和i的父亲相连,i这颗子树所形成的最少链数,dp[i][1]表示i和i的父亲相连,i这颗子树所形成的最少链数,则:

dp[i][0]=∑dp[j][0]+dp[p][1]-dp[p][0] + dp[q][1]-dp[q][0]-1

dp[i][1]=∑dp[j][0]+dp[p][1]-dp[p][0]

其中,j是i的子节点,p是满足dp[j][1]-dp[j][0]最小的j,q是满足dp[j][1]-dp[j][0]第二小的j。

  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#pragma comment(linker, "/STACK:10240000")
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; #define X first
#define Y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(a)) typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull; //#ifndef ONLINE_JUDGE
void RI(vector<int>&a,int n){a.resize(n);for(int i=;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?:-;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?:-;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
//#endif
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);} const double PI = acos(-1.0);
const int INF = 1e9 + ;
const double EPS = 1e-12; /* -------------------------------------------------------------------------------- */ const int maxn = 1e6 + ; pii E[maxn * ];
int SZ;
int Next[maxn * ];
int last[maxn];
int son[maxn]; void add(int u, int v) {
E[SZ ++] = mp(u, v);
E[SZ ++] = mp(v, u);
Next[SZ - ] = last[u];
last[u] = SZ - ;
Next[SZ - ] = last[v];
last[v] = SZ - ;
} int vis[maxn], dp[maxn][]; void dfs(int rt) {
vis[rt] = true;
int ans = , minv1 = INF, minv2 = INF, sum = , sum1 = , cnt = ;
for (int i = last[rt]; ~i; i = Next[i]) {
int v = E[i].Y;
if (!vis[v]) {
dfs(v);
cnt ++;
sum += dp[v][];
sum1 += dp[v][];
int buf = dp[v][] - dp[v][];
if (buf < minv1) {
minv2 = minv1;
minv1 = buf;
}
else {
if (buf < minv2) minv2 = buf;
}
}
}
if (cnt == ) dp[rt][] = dp[rt][] = ;
else if (cnt == ) dp[rt][] = dp[rt][] = sum1;
else if (cnt >= ) {
dp[rt][] = sum + minv1 + minv2 - ;
dp[rt][] = sum + minv1;
}
// printf("%d: %d %d\n", rt, dp[rt][0], dp[rt][1]);
} int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
int T;
cin >> T;
while (T --) {
int n;
cin >> n;
SZ = ;
fillchar(last, - );
fillchar(Next, - );
for (int i = ; i < n; i ++) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
}
fillchar(vis, );
dfs();
cout << dp[][] * - << endl;
}
return ;
}

[hdu4714 Tree2cycle]树形DP的更多相关文章

  1. HDU 4714 Tree2cycle (树形DP)

    题意:给定一棵树,断开一条边或者接上一条边都要花费 1,问你花费最少把这棵树就成一个环. 析:树形DP,想一想,要想把一棵树变成一个环,那么就要把一些枝枝叶叶都换掉,对于一个分叉是大于等于2的我们一定 ...

  2. hdu 4717 Tree2cycle(树形DP)

    Tree2cycle Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)Tot ...

  3. hdu4714(树形dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4714 题意:给你一棵树,,其中每去掉一条边或加一条边的代价均为1,让你求出将其变成一个圆的最小代价. ...

  4. HDU 4714 Tree2cycle (树形DP)

    Tree2cycle Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)Tot ...

  5. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  6. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  7. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  8. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  9. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

随机推荐

  1. vs 类型定义及语句,随机数

    1  类型定义: 1)小数: 类型         变量名           赋值 decimal       d   :              d=1.2m float             ...

  2. 详解 Lambda表达式

    Lambda表达式 概述: Lambda 是一个匿名函数, 我们可以把 Lambda表达式理解为是一段可以传递的代码 (将代码像数据一样进行传递) 可以写出更简洁.更灵活的代码. 作为一种更紧凑的代码 ...

  3. [转]sql二次注入

    01 二次注入原理 二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入.防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据 ...

  4. java-锁膨胀的过程

    先来看个奇怪的demo public class A { int i=0; // boolean flag =false; public synchronized void parse(){ i++; ...

  5. MVC-路由解析

    MVC程序入口 Global.asax.cs 执行Application_Start 方法 *默认路由 *静态路由,访问链接只需要域名加路由url固定值就行了 *替换控制器,或方法名, *正则路由 方 ...

  6. OAuth-授权机制

    一.应用场景 有一个"云冲印"的网站,可以将用户储存在Google的照片,冲印出来.用户为了使用该服务,必须让"云冲印"读取自己储存在Google上的照片. 问 ...

  7. LeetCode 面试题51. 数组中的逆序对

    面试题51. 数组中的逆序对 题目来源:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/ 题目 在数组中的两个数字,如果 ...

  8. js获取数组中最大值

    1.es6拓展运算符... Math.max(...arr) 2.es5 apply(与方法1原理相同) Math.max.apply(null,arr) 3.for循环 let max = arr[ ...

  9. 报错:require_once cannot allocate memory----php,以前自己弄的稍微有点特殊的开发环境

    最近出现过一个问题,值得记录 类似于这样的报错的问题: Warning: require_once(/www/app/somecomponent.php): failed to open stream ...

  10. 开发一款图片压缩工具(三):使用 click 实现命令行

    上一篇实现了图片的压缩函数.现在如果需要对图片进行压缩,可以调用实现的函数进行压缩: pngquant_compress('elephant.png', force=True, quality=20) ...