DP Intro - poj 1947 Rebuilding Roads(树形DP)
版权声明:本文为博主原创文章,未经博主允许不得转载。
|
Rebuilding Roads
Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The cows didn't have time to rebuild any extra roads, so now there is exactly one way to get from any given barn to any other barn. Thus, the farm transportation system can be represented as a tree.
Farmer John wants to know how much damage another earthquake could do. He wants to know the minimum number of roads whose destruction would isolate a subtree of exactly P (1 <= P <= N) barns from the rest of the barns. Input * Line 1: Two integers, N and P
* Lines 2..N: N-1 lines, each with two integers I and J. Node I is node J's parent in the tree of roads. Output A single line containing the integer that is the minimum number of roads that need to be destroyed for a subtree of P nodes to be isolated.
Sample Input 11 6 Sample Output 2 Hint [A subtree with nodes (1, 2, 3, 6, 7, 8) will become isolated if roads 1-4 and 1-5 are destroyed.]
Source |
题意:
给你一棵树,求最少剪掉几条边使能够得到一个p个节点的树。
思路:
用dp[i][j]代表以i为根的子树要变成j个节点需要剪掉的边数。
考虑子节点的时候不用考虑它与父节点的那条边,就当不存在,那么最后求的的最小边数加1就行了。
考虑一个节点时,有两种选择,要么剪掉跟子节点相连的边,则dp[i][j] = dp[i][j]+1;
要么不剪掉,则dp[i][j] = max(dp[i][j], dp[i][k]+dp[son][j-k]);
然后随便以一条边dfs求解就行了。
为什么可以这样求解呢。
对于树上的一个节点。要么在待求解子树中。要么不在。在的话即dp[i][p]中。不然的话就肯定在其它子树上了。
详细见代码:
- #include <iostream>
- #include<stdio.h>
- #include<string.h>
- using namespace std;
- const int maxn=250;
- const int INF=0x3f3f3f3f;
- struct node
- {
- int v;
- node *next;
- } edge[maxn<<1],*head[maxn];
- int n,m,cnt,dp[maxn][maxn];
- void adde(int u,int v)
- {
- edge[cnt].v=v;
- edge[cnt].next=head[u];
- head[u]=&edge[cnt++];
- }
- void dfs(int fa,int u)
- {
- int i,j,v,mm=INF;
- node *p;
- dp[u][1]=0;
- for(p=head[u];p!=NULL;p=p->next)
- {
- v=p->v;
- if(v==fa)
- continue;
- dfs(u,v);
- for(i=m;i>=1;i--)//01背包。从大到小装
- {
- mm=dp[u][i]+1;//不要该子树.
- for(j=1;j<i;j++)//要该子树
- mm=min(mm,dp[u][j]+dp[v][i-j]);
- dp[u][i]=mm;
- }
- }
- }
- int main()
- {
- int i,u,v,ans;
- while(~scanf("%d%d",&n,&m))
- {
- cnt=0;
- memset(head,0,sizeof head);
- memset(dp,0x3f,sizeof dp);
- for(i=1;i<n;i++)
- {
- scanf("%d%d",&u,&v);
- adde(u,v);
- adde(v,u);
- }
- dfs(1,1);
- ans=dp[1][m];
- for(i=1;i<=n;i++)
- ans=min(ans,dp[i][m]+1);//加1是因为根转移了
- printf("%d\n",ans);
- }
- return 0;
- }
DP Intro - 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[i][j]表示以i为根的子树要变成有j个节点的状态需要减掉的边数. 考虑状态转移的时候不考虑i的父亲节点,就当不存在.最后统计最少减去边数的 时候+1. 考虑一个节点时,有两种选择,要么 ...
- 树形dp(poj 1947 Rebuilding Roads )
题意: 有n个点组成一棵树,问至少要删除多少条边才能获得一棵有p个结点的子树? 思路: 设dp[i][k]为以i为根,生成节点数为k的子树,所需剪掉的边数. dp[i][1] = total(i.so ...
- 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
Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 10653 Accepted: 4884 Des ...
- POJ 1947 Rebuilding Roads (树dp + 背包思想)
题目链接:http://poj.org/problem?id=1947 一共有n个节点,要求减去最少的边,行号剩下p个节点.问你去掉的最少边数. dp[u][j]表示u为子树根,且得到j个节点最少减去 ...
- 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..... Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8188 Accepted: ...
随机推荐
- Currying and Uncurrying Js
//反科里化Function.prototype.uncurrying = function() { var _this = this; return function() { return Func ...
- .NET基础 (01).NET基础概念
.NET基础概念 1 什么是CTS.CLS和CLR2 开发和运行.NET程序需要的最基本环节是什么3 .NET是否支持多编程语言开发4 CLR技术和COM技术的比较5 什么是程序集和应用程序域 1 什 ...
- 团体程序设计天梯赛L1-025 正整数A+B 2017-03-23 22:47 61人阅读 评论(0) 收藏
L1-025. 正整数A+B 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 本题的目标很简单,就是求两个正整数A和B的和,其中 ...
- JavaScript 类型转换(2)
隐式类型转换 1. var a = "123"; a++; 这时候会将调用Number("123")将"123"转换成数字类型,然后再自增. ...
- MVC下EF添加上下文
这里我们用Code First方法创建数据库表.这个方法简单点说就是先创建Model再根据Model生成数据库表. 为了方便起见,这里用的数据库是Visual Studio自带的LocalDb. 数据 ...
- c#设计模式系类:亨元模式
一.引言 在软件开发过程中,如果我们需要重复使用某个对象的时候,如果我们重复地使用new创建这个对象的话,这样我们在内存就需要多次去申请内存空间了,这样可能出现内存使用越来越多的情况,这样的问题是非常 ...
- Asp.Net Core下的两种路由配置方式
与Asp.Net Mvc创建区域的时候会自动为你创建区域路由方式不同的是,Asp.Net Core下需要自己手动做一些配置,但更灵活了. 我们先创建一个区域,如下图 然后我们启动访问/Manage/H ...
- Linux下卸载删除.Net Core
最近在技术博客和技术交流群遇到很多小伙伴们在Linux下更新或者安装.Net Core SDK后dotnet命令无法识别等问题,现如下解决: 卸载SDK命令 sudo yum remove dotne ...
- mongodb 片键
mongodb 片键 mongodb的片键是很难控制的,没有完美的片键,只能均衡即可: 片键的方案: 1.id的hashed: 作为第一个方案,你可以使用数据文档_id的哈希作为片键. 这个方案能够 ...
- 读取二元组列表,打印目录的层级结构-----C++算法实现
要求是--某个文件中存储了一个最多3层的层级结构,其中每个元素都是一个自然数,它的存储方法是一个二元组的列表,每个二元组的形式为:(元素,父元素).现在希望能够通过读取该二元组列表,打印出目录的层级结 ...