Component
Problem Description
Given a tree with weight assigned to nodes, find out minimum total weight connected component with fixed number of node.
Input
The first line contains a single integer n .
The second line contains n integers w1,w2,…,wn . wi denotes the weight of the node i .
The following (n−1) lines with two integers ai and bi , which denote the edge between ai and bi .
Note that the nodes are labled by 1,2,…,n .
( 1≤n≤2⋅103,1≤wi≤105 )
Output
n integers c1,c2,…,cn . ci stands for the minimum total weight component with i nodes.
Sample Input
3 1 2 3 1 2 2 3
Sample Output
1 3 6
Source
Manager
不能偷懒 一定要坚持把博客写下去,这次带来的是我比较擅长的树形DP,这次的题目也是简单明了,用Matrix67的话来说,这种题目有种数学的美感,好了,不强行扯关系了,题目大意为给出个树,以及树上的价值,共有n个点,然后让你求1--n个连起来的节点分别最大价值为多少,注意是要连起来的,不然太好做了,不过连起来也好做。核心就在于这个转移方程了,
for(i=cnt[root];i>=1;i--)
for(j=0;j<=min(i,cnt[child]);j++)
{
if(i-j==0) continue;
dp[root][i]=min(dp[root][i],dp[child][j]+dp[root][i-j]);
}
用的是记忆化搜索DP,先深搜把一个个的儿子节点做完,然后每完成一个儿子节点,就更新当前根节点的不同个数点连起来的最大值,因为要连起来,所以i-j不能为0,即根节点必须选中。总的来说是一道基础树形DP,适合刚接触这方面题目的人。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<cmath>
#define MM(a,t) memset(a,t,sizeof(a))
#define INF 1e9
typedef long long ll;
#define mod 1000000007
using namespace std;
struct treenode{
int child,bro;
}tr[2010];
int n,st;
int a[2010],dp[2010][2010],cnt[2010];
bool fp[2010];
int res[2010];
void jicot(int root)
{
int child;
cnt[root]=1;
child=tr[root].child;
while(child!=-1)
{
jicot(child);
cnt[root]+=cnt[child];
child=tr[child].bro;
}
}
void DFSDP(int root)
{
dp[root][0]=0;
dp[root][1]=a[root];
int i,j,child;
child=tr[root].child;
while(child!=-1)
{
DFSDP(child);
for(i=cnt[root];i>=1;i--)
for(j=0;j<=min(i,cnt[child]);j++)
{
if(i-j==0) continue;
dp[root][i]=min(dp[root][i],dp[child][j]+dp[root][i-j]);
}
child=tr[child].bro;
}
}
void jires(int root)
{
int child,i,j;
for(i=1;i<=cnt[root];i++)
res[i]=min(res[i],dp[root][i]);
child=tr[root].child;
while(child!=-1)
{
jires(child);
child=tr[child].bro;
}
}
int main()
{
int i,j,child;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++) scanf("%d",&a[i]);
MM(tr,-1); MM(fp,0); MM(cnt,0);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) dp[i][j]=INF;
for(i=1;i<=n;i++) res[i]=INF;
for(i=1;i<n;i++)
{
int s,e;
scanf("%d%d",&s,&e);
fp[e]=1;
child=tr[s].child;
if(child==-1)
tr[s].child=e;
else
{
while(tr[child].bro!=-1) child=tr[child].bro;
tr[child].bro=e;
}
}
for(i=1;i<=n;i++)
if(fp[i]==0)
{
st=i;
break;
}
jicot(st);
DFSDP(st);
/*for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++) cout<<dp[i][j]<<' ';
cout<<endl;
}*/
jires(st);
for(i=1;i<n;i++) printf("%d ",res[i]); printf("%d\n",res[n]);
}
return 0;
}