题目来源:https://biancheng.love/contest-ng/index.html#/34/problems
题目描述
Nova君来到神奇宝贝中心,准备从存储机中挑选若干个Pockmon去挑战最后的四天王和联盟冠军。Nova君现在有N只可挑选的Pockmon,对于第 i 只Pockmon,他的体总为 wi ,战斗力为 vi 。现在联盟规定,只能携带总重量为M的Pockmon进行挑战。那么,Nova君要怎么挑选才能使战斗力最强呢?大家肯定会说,这不是个简单的背包问题嘛?嗯,大概。但是现在有个问题,由于某些Pockmon在冒险的途中,和存储机内的其他Pockmon产生了羁绊,有可能对另一只Pokmon产生依赖,非得被依赖的那只被选中才能发挥战斗力,否则只能是个战斗力为0的卖萌生物而已,好在每只Pockmon都很专情,只会依赖一只(或者不依赖)。
PS:
(1) 依赖关系不对称,即,若A依赖B,B不一定依赖A,俗称beitai;
(2) 可能出现这样的情况:A依赖B,B依赖C,C依赖A,俗称love triangle,当然也有可能是多边形(悲伤脸)
(3) 保证不会出现自己依赖自己的情况
输入
多组测试数据(组数不超过10),对于每组数据,输入4行,第一行是两个正整数N,M,表示Pockmon总数和联盟允许的最大重量,第二行包含N个正整数w1,w2...wn,表示第 i 个Pockmon的重量,第三行包含N个正整数v1,v2...vn,表示第 i 个Pockmon的战斗力,第四行包含N个正整数D1,D2...Dn,表示第 i 个Pockmon依赖的Pockmon的序号,如果没有依赖对象,则 Di=0。
PS:输入数据都在INT范围内
输出
对于每组数据,输出一行,表示战斗力的最大值
输入样例
3 10
4 5 6
2 3 4
3 1 2
3 10
4 5 6
2 3 4
0 1 1
输出样例
0
6
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int e=505; 5 int n,m,tmpw=0,tmpn; 6 int w[e]= {0},v[e]= {0},b[e]= {0},c[e]= {0},f[e][5*e]= {0},d[e]= {0}; 7 bool mapp[e][e]= {0}; 8 9 void floride() 10 { 11 for(int i=1; i<=n; i++) //弗洛里德判断是否有环; 12 for(int j=1; j<=n; j++) 13 for(int k=1; k<=n; k++) 14 if(mapp[k][i]==1 && mapp[i][j]==1) 15 mapp[k][j]=1; 16 } 17 18 19 void merge()//合点 20 { 21 tmpn=n; 22 for(int i=1; i<=tmpn; i++) 23 for(int j=1; j<=tmpn; j++) 24 { 25 if(mapp[i][j]==1 && mapp[j][i]==1 && i!=j && w[i]>0 && w[j]>0)//如果是新环; 26 { 27 tmpn++; 28 v[tmpn]=v[i]+v[j]; 29 w[tmpn]=w[i]+w[j]; 30 tmpw--; 31 w[i]=tmpw; 32 w[j]=tmpw; //tmpw+tmpn永远等于最开始的n 33 } 34 35 //如果j依赖的点被合并(是旧环),且j在环里 36 if(w[d[j]]<0 && w[j]>0 && mapp[j][d[j]]==1 && mapp[j][d[j]]==1) 37 { 38 w[n-w[d[j]]]+=w[j]; 39 v[n-w[d[j]]]+=v[j]; 40 w[j]=w[d[j]]; 41 } 42 43 //如果j依赖的点在环里,但是j不在环里 44 if(w[d[j]]<0 && w[j]>0) 45 if((mapp[j][d[j]]==1 && mapp[d[j]][j]==0) || (mapp[j][d[j]]==0 && mapp[d[j]][j]==1)) 46 d[j]=n-w[d[j]]; 47 } 48 } 49 50 int dfs(int x,int k) 51 { 52 if(f[x][k]>0) return(f[x][k]); 53 if(x==0 || k<=0) return(0); 54 //不取x 55 f[b[x]][k]=dfs(b[x],k); 56 f[x][k]=f[b[x]][k]; 57 int y=k-w[x]; 58 for(int i=0; i<=y; i++) 59 { 60 f[c[x]][y-i]=dfs(c[x],y-i); 61 f[b[x]][i]=dfs(b[x],i); 62 f[x][k]=max(f[x][k],v[x]+f[c[x]][y-i]+f[b[x]][i]); 63 } 64 return(f[x][k]); 65 } 66 67 68 69 int main() 70 { 71 while(cin>>n>>m) 72 { 73 tmpw=0; 74 memset(w,0,sizeof(w)); 75 memset(v,0,sizeof(v)); 76 memset(c,0,sizeof(c)); 77 memset(b,0,sizeof(b)); 78 memset(d,0,sizeof(d)); 79 memset(f,0,sizeof(f)); 80 memset(mapp,0,sizeof(mapp)); 81 82 for(int i=1; i<=n; i++) 83 scanf("%d",&w[i]); 84 for(int i=1; i<=n; i++) 85 scanf("%d",&v[i]); 86 for(int i=1; i<=n; i++) 87 { 88 int a; 89 scanf("%d",&a); 90 d[i]=a; 91 mapp[a][i]=1; 92 } 93 94 floride(); 95 merge(); 96 97 //多叉转二叉 98 for(int i=1; i<=tmpn; i++) 99 if(w[i]>0) 100 { 101 b[i]=c[d[i]]; 102 c[d[i]]=i; 103 } 104 cout<<dfs(c[0],m)<<endl; 105 } 106 }