POJ 1947 Rebuilding Roads (树形DP)
题意:给一棵树,在树中删除一些边,使得有一个连通块刚好为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)的更多相关文章
- POJ 1947 Rebuilding Roads 树形DP
Rebuilding Roads Description The cows have reconstructed Farmer John's farm, with its N barns (1 & ...
- POJ 1947 Rebuilding Roads 树形dp 难度:2
Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 9105 Accepted: 4122 ...
- DP Intro - poj 1947 Rebuilding Roads(树形DP)
版权声明:本文为博主原创文章,未经博主允许不得转载. Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissi ...
- [poj 1947] Rebuilding Roads 树形DP
Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 10653 Accepted: 4884 Des ...
- POJ 1947 Rebuilding Road(树形DP)
Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, n ...
- POJ 1947 Rebuilding Roads (树dp + 背包思想)
题目链接:http://poj.org/problem?id=1947 一共有n个节点,要求减去最少的边,行号剩下p个节点.问你去掉的最少边数. dp[u][j]表示u为子树根,且得到j个节点最少减去 ...
- 树形dp(poj 1947 Rebuilding Roads )
题意: 有n个点组成一棵树,问至少要删除多少条边才能获得一棵有p个结点的子树? 思路: 设dp[i][k]为以i为根,生成节点数为k的子树,所需剪掉的边数. dp[i][1] = total(i.so ...
- POJ 1947 Rebuilding Roads
树形DP..... Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8188 Accepted: ...
- POJ1947 - Rebuilding Roads(树形DP)
题目大意 给定一棵n个结点的树,问最少需要删除多少条边使得某棵子树的结点个数为p 题解 很经典的树形DP~~~直接上方程吧 dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v] ...
- POJ 1947 Rebuilding Roads(树形DP)
题目链接 题意 : 给你一棵树,问你至少断掉几条边能够得到有p个点的子树. 思路 : dp[i][j]代表的是以i为根的子树有j个节点.dp[u][i] = dp[u][j]+dp[son][i-j] ...
随机推荐
- Sudo环境变量继承
sudo中默认配置会重置环境变量,所以使用sudo的时候需要小心这点.如何让sudo继承我们需要的环境变量?有如下两种方法: #sudo visudo 或者 #vi /etc/sudoers ...
- 1.5 Hive初步使用和安装MySQL
一.HQL初步试用 1.创建一个student表 #创建一个student表 hive> create table student(id int, name string) ROW FORMAT ...
- 【Linux学习】Linux文件系统4—Linux文件硬链接与软连接
Linux文件系统4-Linux文件硬链接与软连接 inode:索引节点 (连接文件)link 一.文件硬链接 1.Linux文件系统中,inode只相同的文件是硬链接文件 2.不同文件名,inode ...
- 20个Flutter实例视频教程-第05节: 酷炫的路由动画-1
视屏地址: https://www.bilibili.com/video/av39709290/?p=5 博客地址: https://jspang.com/post/flutterDemo.html# ...
- 每次打开office 2013都提示配置进度,必须得等他下完然后重启,重启完了在打开,还是提示配置进度,怎么解决
方法一: 我用下面的方法完美解决.在控制面板中1.删除旧版本2010 或者20032.删除激活程序3.重装2013激活程序done 方法二: 我把WPS卸载了就好了. 方法三: 我是按这个方法解决的, ...
- 强大的在线web编辑器UEditor
UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码. UEditor在线演示地址:http://u ...
- Unity2D研究院之自动生成动画、AnimationController、Prefab(一)
http://www.xuanyusong.com/archives/3243 国庆了,回家了.时刻还是要吃一颗学习的心,在家了也要抽出时间好好学习一下.之前MOMO一直没研究过Unity2D,今天研 ...
- iOS开发 - 线程与进程的认识与理解
进程: 进程是指在系统中正在运行的一个应用程序,比如同时打开微信和Xcode,系统会分别启动2个进程; 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内; 线程: 一个进程要想执行任务 ...
- java操作mongodb数据库实现新建数据库,新建集合,新建文档
*首先明确一点,要通过java代码创建mongodb数据库实例,需要同时创建集合和文档. 代码实现: /* 建立与mongodb数据库的连接,可指定参数,如:MongoClient client = ...
- [題解]luogu_P1613跑路(最短路/倍增)
首先要知道不能跑最短路,因為只有整2^k才能一秒到達,和倍增有關 所以我們想知道任意兩點間能否存在一條2^k長度的路徑,數據很小,可以考慮floyd 把倍增和floyd結合起來考慮發現如果i到k,k到 ...