POJ-1947 Rebuilding Roads (树形DP+分组背包)
2016-04-02 23:36
537 查看
题目大意:将一棵n个节点的有根树,删掉一些边变成恰有m个节点的新树。求最少需要去掉几条边。
题目分析:定义状态dp(root,k)表示在以root为根节点的子树中,删掉一些边变成恰有k个节点的新树需要删去的最少边数。对于根节点root的某个儿子son,要么将son及其所有的子节点全部删掉,则dp(root,k)=dp(root,k)+1,只需删除root与son之间的边;要么在son的子树中选出一些边删掉,构造出有j个节点的子树,状态转移方程为dp(root,k)=max(dp(root,k),dp(son,j)+dp(root,k-j))。
代码如下:
题目分析:定义状态dp(root,k)表示在以root为根节点的子树中,删掉一些边变成恰有k个节点的新树需要删去的最少边数。对于根节点root的某个儿子son,要么将son及其所有的子节点全部删掉,则dp(root,k)=dp(root,k)+1,只需删除root与son之间的边;要么在son的子树中选出一些边删掉,构造出有j个节点的子树,状态转移方程为dp(root,k)=max(dp(root,k),dp(son,j)+dp(root,k-j))。
代码如下:
# include<iostream> # include<cstdio> # include<cstring> # include<vector> # include<algorithm> using namespace std; const int N=155; const int INF=1000000000; int n,m; bool flag ; int dp ; vector<int>e ; void init() { int a,b; for(int i=1;i<=n;++i){ e[i].clear(); for(int j=0;j<=m;++j) dp[i][j]=INF; } memset(flag,false,sizeof(flag)); for(int i=1;i<n;++i){ scanf("%d%d",&a,&b); e[a].push_back(b); flag[b]=true; } } void dfs(int u) { dp[u][1]=0; for(int i=0;i<e[u].size();++i){ int v=e[u][i]; dfs(v); for(int j=m;j>=1;--j){ dp[u][j]+=1; for(int k=1;k<j;++k){ ///k从1循环到j-1,一定不能从0循环到j dp[u][j]=min(dp[u][j],dp[v][k]+dp[u][j-k]); } } } } void solve() { int ans=INF; for(int i=1;i<=n;++i){ if(flag[i]) continue; dfs(i); ans=dp[i][m]; break; } for(int i=1;i<=n;++i) ans=min(ans,dp[i][m]+1); printf("%d\n",ans); } int main() { while(~scanf("%d%d",&n,&m)) { init(); solve(); } return 0; }
相关文章推荐
- 【9-3】迭代dict的value
- queryTask
- uva 1584.Circular Sequence
- 三、安卓UI学习(1)
- 理解 Android Build 系统
- HDU1159 && POJ1458:Common Subsequence(LCS)
- 基于WindowsIocp及Duilib的服务器
- Android UI基础——CheckBox&RadioButton控件
- poj 2533 Longest Ordered Subsequence(LIS)
- UI控件--上下文Menu
- 苹果开发工具:Xcode和Interface Builder
- IOS 使用Interface Builder开发界面入门与技巧
- UI控件--PopWindow
- 第63课:Spark SQL下Parquet内幕深度解密学习笔记
- HD 1159 Common Subsequence (最长公共子序列)
- UI控件--AlertDialog
- Android引导动画库:TourGuide
- POJ 1679 The Unique MST 次小生成树
- POJ 1679 The Unique MST 次小生成树
- 第62课:SparkSQL下的Parquet使用最佳实践和代码实践学习笔记