tarjan缩点后即为根,然后就是简单的树型DP
然而DP花了我好长时间QAQ得找个时间练DP才行
1 #include<bits/stdc++.h> 2 #define inc(i,l,r) for(int i=l;i<=r;i++) 3 #define dec(i,l,r) for(int i=l;i>=r;i--) 4 #define link(x) for(edge *j=h[x];j;j=j->next) 5 #define mem(a) memset(a,0,sizeof(a)) 6 #define inf 1e9 7 #define ll long long 8 #define succ(x) (1<<x) 9 #define NM 500+5 10 using namespace std; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 14 while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); 15 return x*f; 16 } 17 struct edge{ 18 int t,v; 19 edge *next; 20 }e[2*NM],*h[NM],*o=e; 21 void add(int x,int y){ 22 o->t=y;o->next=h[x];h[x]=o;o++; 23 } 24 int n,m,a[NM],b[NM],_d[NM][NM],d[NM],suc[NM],low[NM],_x,_y,_t,tot,cnt,ans; 25 bool v[NM]; 26 stack<int >s; 27 void dfs(int x){ 28 d[x]=low[x]=++tot;s.push(x); 29 link(x) 30 if(!d[j->t]){ 31 dfs(j->t); 32 low[x]=min(low[x],low[j->t]); 33 }else if(!suc[j->t]) 34 low[x]=min(low[x],low[j->t]); 35 if(d[x]==low[x]){ 36 int t;cnt++; 37 do{ 38 t=s.top();s.pop(); 39 suc[t]=cnt; 40 }while(x!=t); 41 } 42 } 43 void dp(int x){ 44 inc(i,a[x],m)_d[x][i]=b[x]; 45 link(x){ 46 dp(j->t); 47 dec(k,m,a[x]) 48 inc(i,a[j->t],k-a[x]) 49 if(k>=i) 50 _d[x][k]=max(_d[x][k],_d[j->t][i]+_d[x][k-i]); 51 } 52 } 53 int main(){ 54 // freopen("data.in","r",stdin); 55 n=read();m=read(); 56 inc(i,1,n)a[i]=read(); 57 inc(i,1,n)b[i]=read(); 58 inc(i,1,n) 59 if(_x=read()) 60 add(_x,i),v[i]++; 61 inc(i,1,n) 62 if(!v[i])dfs(i); 63 inc(i,1,n) 64 if(!d[i])dfs(i); 65 inc(i,1,cnt){ 66 _x=_y=_t=0; 67 inc(j,1,n) 68 if(suc[j]==i)_x+=a[j],_y+=b[j],_t++; 69 if(_t==1){ 70 inc(j,1,n) 71 if(suc[j]==i&&!v[j]) 72 add(0,j); 73 }else{ 74 a[++n]=_x;b[n]=_y; 75 add(0,n); 76 inc(k,1,n) 77 if(suc[k]==i) 78 link(k) 79 if(suc[j->t]!=i)add(n,j->t); 80 } 81 } 82 dp(0); 83 inc(i,1,m)ans=max(ans,_d[0][i]); 84 printf("%d\n",ans); 85 return 0; 86 }