题目是问把一棵树通过剪边、加边形成一个环的最小代价。

分成两步,先把树剪成一些链,再把链连接成一个环。

设一棵有n个节点的树,剪掉X条边后,形成L条链。

那么代价为X+L。

n-1-X=edgeNum(L条链) ① //原本有n-1条边,剪掉X条,还剩edgeNum(L条链)条

edgeNum(L条链)+L=n ② //L条链的这些边+L条边形成一个有n条边的环

由①、②得到,L=X+1

则代价为 X+L=2*L-1=2*X+1。

问题转化成了,把一棵树剪成一些链,最少能剪成几条链?或者,最少需要剪掉多少条边?

我觉得到了这一步问题就好解决了,我是树形dp搞的,求的是最少能剪成几条链。

dp[u][0]表示u节点是所在链的端点时,以u节点为根节点的子树形成的最少的链数。

dp[u][1]表示u节点是所在链的中间的点时,以u节点为根节点的子树形成的最少的链数。

然后就可以转移了。

 #include<cstdio>
#include<cstring>
#include<vector>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N = ;
const int inf = N; vector<int> G[N];
int dp[N][]; inline int min(int a,int b) {return a<b?a:b;} void dfs(int u,int fa)
{
int sz = G[u].size();
int v,cld=,sum=,min1=inf,min2=inf,temp;
for(int i=;i<sz;i++)
{
v = G[u][i];
if( v!=fa )
{
cld++;
dfs(v,u);
temp = min(dp[v][],dp[v][]);
sum += temp;
temp = dp[v][] - temp;
if( temp<min1 ) {min2=min1;min1=temp;}
else if( temp<min2 ) min2=temp;
}
}
if( !cld ) dp[u][]=,dp[u][]=inf;
else if( ==cld ) dp[u][]=sum+min1,dp[u][]=inf;
else
{
dp[u][] = sum + min1;
dp[u][] = sum + min1 + min2 - ;
}
} int main()
{
int T;
int n,u,v; //freopen("4714.in","r",stdin);
//freopen("myout.txt","w",stdout);
scanf("%d",&T);
while( T-- )
{
scanf("%d",&n);
for(int i=;i<=n;i++) G[i].clear();
for(int i=;i<n-;i++)
{
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(,);
printf("%d\n",*min(dp[][],dp[][])-);
}
return ;
}

hdu4714 Tree2cycle 把树剪成链的更多相关文章

  1. 介绍一个可以将Expression表达式树解析成Transact-SQL的项目Expression2Sql

    一.Expression2Sql介绍 Expression2Sql是一个可以将Expression表达式树解析成Transact-SQL的项目.简单易用,几分钟即可上手使用,因为博主在设计Expres ...

  2. MS - 1 - 把二元查找树转变成排序的双向链表

    ## 1. 把二元查找树转变成排序的双向链表 ## ### 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表. ### 要求不能创建任何新的结点,只调整指针的指向. 10       ...

  3. 二元查找树转变成排序的双向链表之C#算法实现

    此题为July在CSDN发布的微软编程面试100题中的第一题,觉得蛮有趣的,今天也拿过来玩玩,July的代码用的是C++实现,可能因为有指针的原因吧,感觉看起来相对比较容易理解整个的实现过程,而我,试 ...

  4. Codeforces295A - Greg and Array(线段树的成段更新)

    题目大意 给定一个序列a[1],a[2]--a[n] 接下来给出m种操作,每种操作是以下形式的: l r d 表示把区间[l,r]内的每一个数都加上一个值d 之后有k个操作,每个操作是以下形式的: x ...

  5. P1880 [NOI1995]石子合并 区间dp+拆环成链

    思路 :一道经典的区间dp  唯一不同的时候 终点和起点相连  所以要拆环成链  只需要把1-n的数组在n+1-2*n复制一遍就行了 #include<bits/stdc++.h> usi ...

  6. 【Data structure & Algorithm】把二元查找树转变成排序的双向链表

    把二元查找树转变成排序的双向链表 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表,要求不能创建任何新节点,只调整指针指向. 比如将二元查找树 10 /       \ 6       ...

  7. poj 1179 $Polygon$(断环成链)

    Polygon \(solution:\) upd:还是多讲一下,这道题基本上可以说是一道思维题.一道结论题.一道考验你动态规划基本功是否扎实的题目.因为这道题的数据范围很小,思考一下总能想到断环成链 ...

  8. [hdu4714 Tree2cycle]树形DP

    题意:给一棵树,删边和加边的代价都为1,求把树变成一个圈所花的最小代价. 思路:对原树进行删边操作,直到将原树分成若干条链,然后通过在链之间添加边形成圈,由于删边和加边一一对应,且最后需要额外一条边连 ...

  9. HDU 4714 Tree2cycle(树状DP)(2013 ACM/ICPC Asia Regional Online ―― Warmup)

    Description A tree with N nodes and N-1 edges is given. To connect or disconnect one edge, we need 1 ...

随机推荐

  1. linux 输入子系统(2)----简单实例分析系统结构(input_dev层)

    实例代码如下: #include <linux/input.h> #include <linux/module.h> #include <linux/init.h> ...

  2. linux内核中sys_poll()的简化分析

    app:poll or select; kernel: sys_poll(); do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,st ...

  3. Microsoft Visual Studio Ultimate 2012 旗舰版 有效注册密钥

    Microsoft Visual Studio Ultimate 2012 旗舰版 有效注册密钥: YKCW6-BPFPF-BT8C9-7DCTH-QXGWC 已经过本人测试 本着分享的精神,希望大家 ...

  4. CR0,CR3寄存器

    驱动在hook系统函数的时候通常要将只读属性暂时的屏蔽掉,主要有三种方法 1.修改CR0寄存器的WP位,使只读属性失效(这是网上用的最多的方法),切忌使用完之后立马修改回来 2.只读的虚拟地址,通过C ...

  5. sublime text2 配置php调试环境

    步骤一: 首先确保你电脑安装了php,并把php设置到环境变量里了. 步骤二: 点击 sublime_text的“工具”->"编译系统"->"编译新系统&qu ...

  6. Jsonp 跨域请求实例

    关于jsonp的一个实例,其实自己也不是很了解,今天下午稍微研究了一下: 简单来说,jsonp就是为了两个不同网站之间数据传递而产生的,主要用于js脚本,因为浏览器本身是禁止跨域访问的: 本机实例: ...

  7. shapefile文件

    基本信息编辑 ESRI公司的Shapefile文件是描述空间数据的几何和属性特征的非拓扑实体矢量数据结构的一种格式. 内容编辑 一个Shapefile文件最少包括三个文件: 主文件(*.shp).-- ...

  8. 兼容IE,Firefox,Opera等浏览器的添加到收藏夹js代码实现

    function AddToFavorites() { var title = document.title; var url = location.href; if (window.sidebar) ...

  9. CLR.via.C#第三版 读书笔记

    第一章 CLR的执行模型 1.1将源代码编译成托管代码 决定将.NET Framework作为自己的开发平台之后,第一步是决定要生成什么类型的应用程序或组件.假定你已经完成了这些次要的细节:一切都已经 ...

  10. Java 数组的三种创建方法

    public static void main(String[] args) { //创建数组的第一种方法 int[] arr=new int[6]; int intValue=arr[5]; //S ...