题意:给一棵树,删边和加边的代价都为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. 极验反爬虫防护分析之slide验证方式下图片的处理及滑动轨迹的生成思路

    本文要分享的内容是去年为了抢鞋而分析 极验(GeeTest)反爬虫防护的笔记,由于篇幅较长(为了多混点CB)我会按照我的分析顺序,分成如下四个主题与大家分享: 极验反爬虫防护分析之交互流程分析 极验反 ...

  2. 详解 迭代器 —— Iterator接口、 ListIterator接口 与 并发修改异常

    (请关注 本人"Collection集合"博文--<详解 Collection集合>) Iterator接口(迭代器): 概述: 对 collection 进行迭代的迭 ...

  3. [YII2] 3步发送邮件,有图有真相!

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABOQAAAIcCAYAAABW0HFSAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjw ...

  4. Python最佳工程实践,建立一个完美的工程项目

    在程序开发时候一套好的开发环境和工具栈,可以帮我们极大的提高开发的效率,避免把大量时间浪费在周边琐事上.本文以Python为例,教大家如何快速打造完美的Python项目开发环境:内容涵盖了模块依赖管理 ...

  5. 实现Nginx Upload 模块 功能上传文件。

    分析(也许我表达的让人难以理解,但是我想说一句,直接实践是最好的.....): 一.Ningx 上传( 1.安装Nginx 的模块文件(upload):https://www.nginx.com/re ...

  6. 关于virtualbox配置centos7的网络问题

    连接方式最好选桥接网卡 原文:https://www.cnblogs.com/zergling9999/p/6026006.html

  7. 2019-2020-1 20199308《Linux内核原理与分析》第六周作业

    <Linux内核分析> 第五章 系统调用的三层机制(下) 5.1 给MenuOS增加命令 强制删除当前menu目录,用get clone重新克隆一个新版本的menu,运行make root ...

  8. 以命令行界面启动 Ubuntu

    1. /etc/default/grub 将GRUB_CMDLINE_LINUX_DEFAULT一行中改为"quiet splash 3" 2. update-grub 3. 重启

  9. awk命令及随机数的产生

    3.sed 操作,将文件第9行至第15行的数据复制到第十六行 sed -i  '9,15H;16G' 文件 4.用awk获取文件中的三行的倒数第二列字段 awk -F":" 'NR ...

  10. iOS开发·runtime原理与实践: 消息转发篇(Message Forwarding) (消息机制,方法未实现+API不兼容奔溃,模拟多继承)...

    本文Demo传送门: MessageForwardingDemo 摘要:编程,只了解原理不行,必须实战才能知道应用场景.本系列尝试阐述runtime相关理论的同时介绍一些实战场景,而本文则是本系列的消 ...