P1272 重建道路
和POJ1947一样。再写一遍增加熟练度。
题目描述
一场可怕的地震后,人们用N个牲口棚(1≤N≤150,编号1..N)重建了农夫John的牧场。由于人们没有时间建设多余的道路,所以现在从一个牲口棚到另一个牲口棚的道路是惟一的。因此,牧场运输系统可以被构建成一棵树。John想要知道另一次地震会造成多严重的破坏。有些道路一旦被毁坏,就会使一棵含有P(1≤P≤N)个牲口棚的子树和剩余的牲口棚分离,John想知道这些道路的最小数目。
输入输出格式
输入格式:
第1行:2个整数,N和P
第2..N行:每行2个整数I和J,表示节点I是节点J的父节点。
输出格式:
单独一行,包含一旦被破坏将分离出恰含P个节点的子树的道路的最小数目。
输入输出样例
输入样例#1:
11 6
1 2
1 3
1 4
1 5
2 6
2 7
2 8
4 9
4 10
4 11
输出样例#1:
2
说明
【样例解释】
如果道路1-4和1-5被破坏,含有节点(1,2,3,6,7,8)的子树将被分离出来
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<vector> 7 using namespace std; 8 const int mxn=200; 9 int n,p; 10 vector<int>e[mxn]; 11 int f[mxn][mxn]; 12 int num[mxn]; 13 void dp(int u){ 14 int i,j,k; 15 num[u]=1; 16 if(!e[u].size()){f[u][1]=0;return;} 17 for(i=0;i<e[u].size();i++){ 18 int v=e[u][i]; 19 dp(v); 20 num[u]+=num[v]; 21 for(j=num[u];j;j--) 22 for(k=1;k<j;++k){ 23 f[u][j]=min(f[u][j],f[u][j-k]+f[v][k]-1); 24 } 25 } 26 return; 27 } 28 int main(){ 29 scanf("%d%d",&n,&p); 30 int i,j; 31 int u,v; 32 for(i=1;i<n;i++){ 33 scanf("%d%d",&u,&v); 34 e[u].push_back(v); 35 num[u]++; 36 } 37 memset(f,0x3f,sizeof f); 38 for(i=1;i<=n;i++){ 39 f[i][1]=num[i]; 40 } 41 dp(1); 42 int ans=f[1][p]; 43 for(i=2;i<=n;i++){ 44 ans=min(ans,f[i][p]+1); 45 } 46 cout<<ans<<endl; 47 return 0; 48 }
本文为博主原创文章,转载请注明出处。