树 - 题目 - Daimayuan Online Judge
题意:
思路:
一开始很自然的去想树形DP
后来发现,根本不能转移呀
然后就不会了
事实上是个背包题
每操作一个结点都会产生Out[u]的贡献,Out[u]表示结点u的出度,然后问你贡献为K的最小操作次数
跑背包即可
请问这是怎么想到的呢?我也不知道,大概手摸样例就能发现性质了(?
Code:
#include <bits/stdc++.h>
//#define int long long
using namespace std;
const int mxn=3e3+10;
const int mxe=3e3+10;
const int Inf=0x3f3f3f3f;
int N,Fa;
int a[mxn];
int Out[mxn],dp[mxn][mxn];
void solve(){
cin>>N;
for(int i=2;i<=N;i++){
cin>>Fa;
Out[Fa]++;
}
memset(dp,0x3f,sizeof(dp));
dp[0][0]=0;
for(int i=1;i<=N;i++){
for(int j=0;j<=N;j++){
dp[i][j]=min(dp[i][j],dp[i-1][j]);
if(j>=Out[i]) dp[i][j]=min(dp[i][j],dp[i-1][j-Out[i]]+1);
}
}
for(int j=1;j<=N;j++){
if(dp[N][j-1]==Inf) cout<<-1<<" \n"[j==N];
else cout<<dp[N][j-1]<<" \n"[j==N];
}
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int __=1;//cin>>__;
while(__--)solve();return 0;
}