题目:
分析:感觉和上一个的选课一样,就是同一根的不同子树之间的关系。需要一个类似背包,但是只能想到这里,后面的想不出来了。
看了题解的dp思路:int B[3005][3005];//表示编号为i的节点所代表的子树在开通j个用户时的最大利润 。
模仿做的第一道树形背包,写下代码,,只有20分,但觉得逻辑没错。:
放弃:树形背包有待突破:
#include<bits/stdc++.h>
using namespace std;
vector<vector<int> > vv;
vector<vector<int> > vv2;
int A[3005];
int B[3005][3005];
int m,n;
void dfs(int x)
{
if(vv[x].size()==0)
{
cin>>A[x];
return ;
}
for(int i=0;i<vv[x].size();i++)
{
dfs(vv[x][i]);
}
}
void f(int x)
{
if(vv[x].size()==0)
{
B[x][1]=A[x];
for(int i=2;i<=n;i++) B[x][i]=-(1<<27);
return;
}
for(int i=0;i<vv[x].size();i++)
{
int c=vv[x][i];
f(c);
if(i==0) for(int i=1;i<=n;i++) B[x][i]=-(1<<30);
for(int k1=n;k1>0;k1--)
{
for(int k2=1;k2<=k1;k2++)
{
B[x][k1]=max(B[x][k1],B[x][k1-k2]+B[c][k2]-vv2[x][i]);
}
}
}
}
int main()
{
cin>>m>>n;
memset(A,-1,sizeof(A));
memset(B,0,sizeof(B));
vector<int> v;
for(int i=0;i<=m;i++)
{
vv.push_back(v);
vv2.push_back(v);
}
for(int i=1;i<=m-n;i++)
{
int a;
cin>>a;
for(int j=0;j<a;j++)
{
int a1,a2;
cin>>a1>>a2;
vv[i].push_back(a1);
vv2[i].push_back(a2);
}
}
dfs(1);
f(1);
for(int i=n;;i--) if(B[1][i]>=0)
{
cout<<i;
return 0;
}
cout<<endl<<"--------"<<endl;
for(int j=1;j<=m;j++)
{
for(int i=0;i<=n;i++) cout<<B[j][i]<<' ';
cout<<endl;
}
}