POJ 1947 Rebuilding Roads
来源:互联网 发布:看门狗mac版 编辑:程序博客网 时间:2024/06/07 02:28
Description
The cows havereconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number1..N) after the terrible earthquake last May. The cows didn't have time torebuild any extra roads, so now there is exactly one way to get from any givenbarn to any other barn. Thus, the farm transportation system can be representedas a tree.
Farmer John wants to know how much damage another earthquake could do. He wantsto know the minimum number of roads whose destruction would isolate a subtreeof exactly P (1 <= P <= N) barns from the rest of the barns.
Input
* Line 1: Twointegers, N and P
* Lines 2..N: N-1 lines, each with two integers I and J. Node I is node J'sparent in the tree of roads.
Output
A single linecontaining the integer that is the minimum number of roads that need to bedestroyed 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
题目大意:有n个点,现在要得到只含有p个点的子树。接着输入n-1条边将n个点相连。问要截断最少截断多少条边能得到只含有p个点的子树。
此题首先可以转化一下。每个点与之相连的点有num[i]个,则,得到含有p个点的子树需要截断的边为∑num[i]-2*(p-1),i为这p个点的编号。式子的得到是,得到的子树内部一共有p-1条边,而∑num[i]将每条边算了两次,即2*(p-1),要得到这个子树就需要截断这个子树外部的边,外部边的数目即,这p个点所含边数的总和减去2*内部的边的数目。而2*(p-1)对于问题来说是固定的。故现在问题就转化成了求p个点所含边数的总和的最小值。
dp[i][j]表示的是含有以i点为根节点的子树含有i点的连续j个点所含边数的总和的最小值。我们可以以任意一个点作为树的根节点进行遍历,每次只用计算其子节点即可。同时,一个问题是dp[i][1]要赋初值为num[i],dp[i]中必须含有点i。
转移方程:dp[i][k] = min(dp[i][k],dp[i][j] + dp[re][k-j]);(re为i的子节点)
#include <iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<vector>#define INF 0x03F3F3F3Fusing namespace std;int n ,p;vector<int> v[160];int num[160];int dp[160][160] ,flag[160];void solve(int x){ flag[x] = 1; for(int i = 0;i < num[x];i++) { if(!flag[v[x][i]]) { solve(v[x][i]); for(int k = p;k>=1;k--) { for(int j = k;j>=1;j--) { if(dp[x][k] > dp[x][j] + dp[v[x][i]][k-j]) { dp[x][k] = dp[x][j] + dp[v[x][i]][k-j]; } } } } }}int main(){ int u ,s ,m; while(~scanf("%d%d",&n,&p)) { memset(flag,0,sizeof(flag)); memset(dp,0x03F3F3F3F,sizeof(dp)); for(int i = 1;i<n;i++) { scanf("%d%d",&u,&s); v[u].push_back(s); v[s].push_back(u); } for(int i = 1;i<=n;i++) { num[i] = v[i].size(); } for(int i = 1;i<=n;i++) { dp[i][1] = num[i]; } solve(1); m = INF; for(int i = 1;i<=n;i++) { if(m > dp[i][p]) { m = dp[i][p]; } } printf("%d\n",m-2*(p-1)); for(int i = 0;i<=n;i++) { v[i].clear(); } } return 0;}
- POJ 1947 Rebuilding Roads
- poj 1947 Rebuilding Roads
- POJ 1947 Rebuilding Roads
- POJ 1947 Rebuilding Roads
- poj 1947 Rebuilding Roads
- POJ 1947 Rebuilding Roads
- POJ 1947 Rebuilding Roads
- poj-1947-Rebuilding Roads
- POJ 1947 Rebuilding Roads
- POJ 1947 Rebuilding Roads
- POJ 1947 Rebuilding Roads
- POJ 1947 Rebuilding Roads
- POJ 1947--Rebuilding Roads
- POJ 1947 Rebuilding Roads
- poj-1947 Rebuilding Roads
- Poj 1947 Rebuilding Roads
- POJ 1947 Rebuilding roads
- 【poj 1947】 Rebuilding Roads
- 手工移除.META.表的错误信息
- Hadoop海量视频、图像分析分布式处理总结
- OCP-1Z0-053-200题-110题-673
- C#下载文件(可显示进度)的方法实现
- 中断体系结构
- POJ 1947 Rebuilding Roads
- sqoop 从 hive 导到mysql遇到的问题
- 控制对类成员的访问
- 榕树群群聊记录05(群号1326585)
- thinkphp查询方式where详解
- hadoop下mahout bayes(贝叶斯)算法研究(1)
- NYOJ 289 苹果
- 揭秘乌云网:中国最大的黑客培训基地?
- 跟我一起学windows初高级调试(1) --你为什么要学调试