poj 1947(树形DP+背包)
2016-04-21 17:52
543 查看
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
Sample Output
Hint
[A subtree with nodes (1, 2, 3, 6, 7, 8) will become isolated if roads 1-4 and 1-5 are destroyed.]
题意:在n个结点n-1条边的树中取m个点所需要的最少切割数.
分析:dp[u][i]代表以u为根节点的子树要得到i个结点的子树需要最少的切割数 如果考虑u的子树v,如果我们在除去v之外的父亲树中取k个点,那么在子树中取i-k个点
dp[u][i] = min(dp[u][k]+dp[v][i-k]) ........1
如果不考虑v,那么我们只需要一刀将子树k与父亲分开即可dp[u][i] = dp[u][i]+1; ..........2
综上述:dp[u][i] = min(1,2)
我们在考虑u的时候,等于u是一个容量为m(m为背包容量)的背包,在子树中取m个结点组成,每个点只有取或不取一个,所以可以将其看成01背包。
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 10663 | Accepted: 4891 |
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 1 2 1 3 1 4 1 5 2 6 2 7 2 8 4 9 4 10 4 11
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.]
题意:在n个结点n-1条边的树中取m个点所需要的最少切割数.
分析:dp[u][i]代表以u为根节点的子树要得到i个结点的子树需要最少的切割数 如果考虑u的子树v,如果我们在除去v之外的父亲树中取k个点,那么在子树中取i-k个点
dp[u][i] = min(dp[u][k]+dp[v][i-k]) ........1
如果不考虑v,那么我们只需要一刀将子树k与父亲分开即可dp[u][i] = dp[u][i]+1; ..........2
综上述:dp[u][i] = min(1,2)
我们在考虑u的时候,等于u是一个容量为m(m为背包容量)的背包,在子树中取m个结点组成,每个点只有取或不取一个,所以可以将其看成01背包。
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <algorithm> #define N 155 using namespace std; int head ; struct Edge{ int u,v,next; }edge ; int indegree ; void addEdge(int u,int v,int &k){ edge[k].u = u,edge[k].v = v; edge[k].next = head[u],head[u]=k++; } int n,m; int dp ;///dp[u][i]代表以u为根节点的子树要得到i个结点的子树需要最少的切割数 /// 如果考虑u的子树v,如果我们在父亲树中取k个点,那么在子树中取i-k个点 ///dp[u][i] = min(dp[u][k],dp[v][i-k]) ///如果不考虑v,那么我们只需要一刀将子树k与父亲分开即可 dp[u][i] = dp[u][i]+1; ///综上述:dp[u][i] = min(min(dp[u][k],dp[v][i-k]),dp[u][i]+1) ///我们在考虑u的时候,等于u是一个容量为m(m为背包容量)的背包,在子树中取m个结点组成,每个点只有取或不取且最多取一次,所以 void dfs(int u){ for(int i=0;i<=m;i++) dp[u][i]=999999; dp[u][1]=0; ///初始化只取自己一个点 for(int k = head[u];k!=-1;k=edge[k].next){ int v = edge[k].v; dfs(v); for(int j=m;j>=1;j--){ ///逆序枚举 dp[u][j]+=1; ///不取子树时 for(int k=1;k<j;k++){ ///父亲树上取得点 int t = j-k; ///子树上取的点 dp[u][j] = min(dp[u][k]+dp[v][t],dp[u][j]); } } } } int main() { while(scanf("%d%d",&n,&m)!=EOF){ memset(indegree,0,sizeof(indegree)); memset(head,-1,sizeof(head)); int tot = 0; int u,v; for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); addEdge(u,v,tot); indegree[v]++; } int root ; for(int i=1;i<=n;i++) if(indegree[i]==0){root = i;break;} //printf("%d\n",root); dfs(root); int ans = dp[root][m]; for(int i=1;i<=n;i++){ ///加一是因为父亲结点和它之间还有边连着 if(dp[i][m]+1<ans) ans = dp[i][m]+1; } printf("%d\n",ans); } return 0; }
相关文章推荐
- Swift 定义函数 参数 返回值
- 通过代理连接go01ge
- spring+websocket整合(springMVC+spring+MyBatis即SSM框架和websocket技术的整合)
- Linux od命令
- ScrollView嵌套EditText联带滑动的解决办法
- 主线程给子线程发送消息
- Activiti框架学习记录-02
- 获取设备UUID
- 转载金阳光测试:关于产品的三类文档
- 今日头条、微信写出阅读量十万+的文章核心技巧解密!
- 麒麟来源堡垒机设计原理
- [ROM] 最新版20150522秋大5.1.1谷歌服务包+谷歌帐号无法登录解决方法
- C#数字千分位问题
- python实现线程池
- 集群多服务器,普通用户SSH访问方法
- 数据链路层
- 物理层
- JS/Jquery得到Select标签显示值和value值
- python基础篇
- spring ioc和aop原理