题意:给一棵树,在树中删除一些边,使得有一个连通块刚好为p个节点,问最少需要删除多少条边?

思路:

  因为任一条边都可能需要被删除,独立出来的具有p个节点的连通块可能在任意一处地方。先从根开始DFS,然后进行树DP,dp[t][i]表示在以t为根的子树中删除i个点需要删除多少条边。dp[t][n-p]有可能是答案了,但是这种仅考虑到从树上脱落掉部分子树,那么留下的连通块通常是与1号点(树根)相连的,那如果所需要的连通块是在某棵子树中呢?将所有可能的子树取出来,若该子树节点数>=p,那么就可以在该子树中再删除一些边,来取得最优解。

  注:若p=n,那么ans=0;若有某棵子树的节点数等于p,那么ans=1。

 //#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <iostream>
#define pii pair<int,int>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=; struct node
{
int from,to,next;
node(){};
node(int from,int to,int next):from(from),to(to),next(next){};
}edge[N*];
int head[N], dp[N][N], cnt[N], n, p, edge_cnt;
void add_node(int from,int to)
{
edge[edge_cnt]=node(from, to, head[from]);
head[from]=edge_cnt++;
} int DFS(int t)
{
int sum=dp[t][]=;
node e;
for(int i=head[t]; i!=-; i=e.next)
{
e=edge[i];
cnt[e.to]=DFS(e.to);
sum+=cnt[e.to]; //统计叶子数量 for(int j=sum; j>; j--)
for(int k=; k<=cnt[e.to] && k<=j; k++)
dp[t][j]=min(dp[t][j], dp[t][j-k]+dp[e.to][k]); //dp值表示至少需要断开多少条边
}
dp[t][sum+]=(t==?:); //断开edge(t,父亲)这条边,以t为根的子树就是sum+1个点了。
return sum+;
} int main()
{
freopen("input.txt", "r", stdin);
int a,b;
while(~scanf("%d%d",&n,&p))
{
memset(head, -, sizeof(head));
memset(dp, 0x3f, sizeof(dp));
memset(cnt, , sizeof(cnt));
edge_cnt=; for(int i=; i<n; i++)
{
scanf("%d%d",&a,&b);
add_node(a, b);
}
cnt[]=DFS(); //根一定是1 int ans=INF;
for(int i=; i<=n; i++)
{
if(cnt[i]-p>=) //子树i去掉cnt[i]-p个点后与i相连的连通块。
ans=min(ans, dp[i][cnt[i]-p]+);
ans=min(ans, dp[i][n-p]); //在此子树中
}
printf("%d\n", ans);
} /*
(1)计算从每棵子树断开k个节点的最少花费。
(2)断开某一子树与父亲的边,再从该子树中断开cnt-p条边(dp值已求),就能获得p个节点的树。
*/
return ;
}

AC代码

POJ 1947 Rebuilding Roads (树形DP)的更多相关文章

  1. POJ 1947 Rebuilding Roads 树形DP

    Rebuilding Roads   Description The cows have reconstructed Farmer John's farm, with its N barns (1 & ...

  2. POJ 1947 Rebuilding Roads 树形dp 难度:2

    Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 9105   Accepted: 4122 ...

  3. DP Intro - poj 1947 Rebuilding Roads(树形DP)

    版权声明:本文为博主原创文章,未经博主允许不得转载. Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissi ...

  4. [poj 1947] Rebuilding Roads 树形DP

    Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 10653 Accepted: 4884 Des ...

  5. POJ 1947 Rebuilding Road(树形DP)

    Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, n ...

  6. POJ 1947 Rebuilding Roads (树dp + 背包思想)

    题目链接:http://poj.org/problem?id=1947 一共有n个节点,要求减去最少的边,行号剩下p个节点.问你去掉的最少边数. dp[u][j]表示u为子树根,且得到j个节点最少减去 ...

  7. 树形dp(poj 1947 Rebuilding Roads )

    题意: 有n个点组成一棵树,问至少要删除多少条边才能获得一棵有p个结点的子树? 思路: 设dp[i][k]为以i为根,生成节点数为k的子树,所需剪掉的边数. dp[i][1] = total(i.so ...

  8. POJ 1947 Rebuilding Roads

    树形DP..... Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8188 Accepted: ...

  9. POJ1947 - Rebuilding Roads(树形DP)

    题目大意 给定一棵n个结点的树,问最少需要删除多少条边使得某棵子树的结点个数为p 题解 很经典的树形DP~~~直接上方程吧 dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v] ...

  10. POJ 1947 Rebuilding Roads(树形DP)

    题目链接 题意 : 给你一棵树,问你至少断掉几条边能够得到有p个点的子树. 思路 : dp[i][j]代表的是以i为根的子树有j个节点.dp[u][i] = dp[u][j]+dp[son][i-j] ...

随机推荐

  1. 三、Chrome开发者工具详解(3)-Timeline面板

    摘自: http://www.cnblogs.com/charliechu/p/5992177.html

  2. kvm详细介绍

    KVM详解,太详细太深入了,经典 2016-07-18 19:56:38 分类: 虚拟化 原文地址:KVM详解,太详细太深入了,经典 作者:zzjlzx KVM 介绍(1):简介及安装 http:// ...

  3. jquery 点击某一行,得到这一行的每个列的数据

    <html><head> <title>test</title> <script src="../Scripts/jquery-1.8. ...

  4. 《剑指offer》面试题16—反转链表

    Node* p1  p2  p3 思路:开始时,p1为NULL,p2=phead,p3=p2—>next.使p2—>next = p1,然后使p1=p2,p2=p3.如果只有1个结点则此时 ...

  5. C++虚继承作用

    C++虚继承可以防止多重继承产生的二义性问题. 虚继承,就是在被继承的类前面加上virtual关键字,这时被继承的类称为虚基类,如下面代码中的base类.虚继承在多重继承的时可以防止二义性. clas ...

  6. [Swift]快速反向平方根 | Fast inverse square root

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  7. 笔记-JavaWeb学习之旅9

    XML Extensible Markup Language 可扩展标记语言 功能:配置文件,在网络中传输 基本语法 1.xml文档的后缀名.xml 2.xml第一行必须定义为文档声明 3.xml文档 ...

  8. 在linux下pycharm无法输入中文

    1.在centos系统下,在pycharm中,输入中文件时,显示的字母,无法显示中文字符. 首先,在centos下安装中文输入法,下面安装的是五笔输入法. a::yum安装ibus的五笔输入法: yu ...

  9. 对单片机C语言的一些误用和总结

    在学习单片机的时候才真正知道C语言是什么它是来干什么的~但是C语言用到嵌入式只是它小小的一部分他的应用还有很多地方呢,呵呵我们这里就不讨论这个了.我们是不是在写程序的时候错误很多就算编译通过了也达不到 ...

  10. python selenium模块调用浏览器的时候出错

    python selenium模块使用出错,这个怎么改 因为不同版本更新不同步问题,浏览器都要另外下一个驱动.