部分の最適化
木を小さく分けてずっと考えてると、最適解が1つだと分かる
速解きは無理
- #include<iostream>
- #include<algorithm>
- #include<vector>
- #include<queue>
- #define lol(i,n) for(int i=0;i<n;i++)
- #define mod 1000000007
- typedef long long ll;
- using namespace std;
- bool dp[5010],cop[5010];
- vector<int> v[1010];
- int index[1010];
- int par[1010];
- int x[1010],y[1010];
- queue<int> Q;
- int main(){
- int n;
- cin>>n;
- lol(i,n)index[i]=0;
- par[0]=-1;
- for(int i=1;i<n;i++){
- cin>>par[i];par[i]--;
- index[par[i]]++;
- v[par[i]].push_back(i);
- }
- for(int i=0;i<n;i++){
- if(index[i]==0)Q.push(i);
- }
- lol(i,n){
- cin>>x[i];
- }
- while(!Q.empty()){
- int i=Q.front();Q.pop();
- if(i==-1)break;
- lol(k,5010)dp[k]=false;
- dp[0]=true;
- int sum=0;
- int visize=v[i].size();
- for(int k=0;k<visize;k++){
- lol(r,5010)cop[r]=false;
- int tmp=v[i][k];
- sum+=x[tmp];
- for(int r=0;r+x[tmp]<5010;r++){
- cop[r+x[tmp]]|=dp[r];
- }
- for(int r=0;r+y[tmp]<5010;r++){
- cop[r+y[tmp]]|=dp[r];
- }
- lol(r,5010)dp[r]=cop[r];
- }
- int maxi=-1;
- for(int k=0;k<=min(sum,x[i]);k++)if(dp[k])maxi=k;
- y[i]=sum-maxi;
- //cout<<"%"<<i<<" "<<x[i]<<" "<<y[i]<<" "<<sum<<" "<<maxi<<endl;
- if(y[i]<0||maxi==-1){
- cout<<"IMPOSSIBLE"<<endl;
- return 0;
- }
- index[par[i]]--;
- if(index[par[i]]==0){
- Q.push(par[i]);
- }
- }
- cout<<"POSSIBLE"<<endl;
- return 0;
- }
実装の練習になった