链接
题目大意:
就是让你做有依赖的背包问题
思路:
1.
首先我们思考出现环的情况:
如果出现了环,也就是说它有两种可能:1是这个环里的数全不选,2是全选。于是我们就可以把它压缩成一个点,具体方式如下:
- 点i所在的环之前没有判断过,是新环。我们将这个环放到数组最后,新加一个点,储存这个环,然后让这两个点的空间标记为负值tmpw,且tmpw+tmpn(新点的下标)等于原来的坐标,我们就可以通过这个坐标找到这个环所在的点。
- 2、点i所在的环之前已经判断过了,是旧环,且i是环的一部分(i还没合并)。那么我们就把i也加到这个环里面,让环的体积,价值相加即可;
- 3、点j所在的环是旧环,但是i不是环的一部分(例如1依赖2,2依赖3,3依赖1。4也依赖1,那么,4所在的是个环,但4不属于环的一部分)。那么,把j的父亲转到环上。
于是,我们就有:
void VL_merge()
{
tmpn=n;
for(int i=1; i<=tmpn; i++)
for(int j=1; j<=tmpn; j++)
{
if(a[i][j]==1&&a[j][i]==1&&w[i]>0&&w[j]>0&&i!=j)
{
tmpn++;
w[tmpn]=w[i]+w[j];
v[tmpn]=v[i]+v[j];
tmpw--;
w[i]=tmpw, w[j]=tmpw;
}
if(a[d[j]][j]==1&&a[j][d[j]]==1&&w[d[j]]<0&&w[j]>0)
{
w[n-w[d[j]]]+=w[j];
v[n-w[d[j]]]+=v[j];
w[j]=w[d[j]];
}
if(w[d[j]]<0&&w[j]>0)
if((a[d[j]][j]==1&&a[j][d[j]]==0)||(a[d[j]][j]==0&&a[j][d[j]]==1))
d[j]=n-w[d[j]];
}
}
2.
我们分析x和它儿子和它爸爸的关系
- 它要在它爸爸选了之后才能选,所以它爸爸的值可以传承到它身上,当作不选它
- 我们类似完全背包的做法,枚举当前还剩的空间,然后可以得出
f[c[x]][y-i]=VL_dfs(c[x], y-i);//枚举儿子的空间
f[b[x]][i]=VL_dfs(b[x], i);//作为它父亲的前传
f[x][k]=max(f[x][k], v[x]+f[c[x]][y-i]+f[b[x]][i]);
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
using namespace std;
const int MAXN=1000;
int n, m, tmpw, tmpn, w[MAXN], v[MAXN], d[MAXN], c[MAXN], b[MAXN];
int a[MAXN][MAXN];
int f[MAXN][MAXN];
void VL_floyed()
{
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
for(int k=1; k<=n; k++)
if(a[k][i]==1&&a[i][j]==1)
a[k][j]=1;//Floyde判断环
}
void VL_merge()
{
tmpn=n;
for(int i=1; i<=tmpn; i++)
for(int j=1; j<=tmpn; j++)
{
if(a[i][j]==1&&a[j][i]==1&&w[i]>0&&w[j]>0&&i!=j)
{
tmpn++;
w[tmpn]=w[i]+w[j];
v[tmpn]=v[i]+v[j];
tmpw--;
w[i]=tmpw, w[j]=tmpw;
}
if(a[d[j]][j]==1&&a[j][d[j]]==1&&w[d[j]]<0&&w[j]>0)
{
w[n-w[d[j]]]+=w[j];
v[n-w[d[j]]]+=v[j];
w[j]=w[d[j]];
}
if(w[d[j]]<0&&w[j]>0)
if((a[d[j]][j]==1&&a[j][d[j]]==0)||(a[d[j]][j]==0&&a[j][d[j]]==1))
d[j]=n-w[d[j]];
}
}
int VL_dfs(int x, int k)
{
if(f[x][k]>0)
return f[x][k];
if(x==0||k<=0)
return 0;
f[b[x]][k]=VL_dfs(b[x], k);
f[x][k]=f[b[x]][k];
int y=k-w[x];
for(int i=0; i<=y; i++)
{
f[c[x]][y-i]=VL_dfs(c[x], y-i);
f[b[x]][i]=VL_dfs(b[x], i);
f[x][k]=max(f[x][k], v[x]+f[c[x]][y-i]+f[b[x]][i]);
}
return f[x][k];
}
int main(){
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++)
scanf("%d", &w[i]);
for(int i=1; i<=n; i++)
scanf("%d", &v[i]);
for(int i=1; i<=n; i++)
{
scanf("%d", &d[i]);
a[d[i]][i]=1;
}
VL_floyed();
VL_merge();
for(int i=1; i<=tmpn; i++)
{
if(w[i]>0)
{
b[i]=c[d[i]];
c[d[i]]=i;
}
}
printf("%d", VL_dfs(c[0], m));
return 0;
}