洛谷P2515 [HAOI2010]软件安装(tarjan缩点+树形dp)

传送门

 

我们可以把每一个$d$看做它的父亲,这样这个东西就构成了一个树形结构

问题是他有可能形成环,所以我们还需要一遍tarjan缩点

缩完点后从0向所有入度为零的点连边

然后再跑一下树形dp就行了

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 using namespace std;
 6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 7 char buf[1<<21],*p1=buf,*p2=buf;
 8 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
 9 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
10 inline int read(){
11     #define num ch-'0'
12     char ch;bool flag=0;int res;
13     while(!isdigit(ch=getc()))
14     (ch=='-')&&(flag=true);
15     for(res=num;isdigit(ch=getc());res=res*10+num);
16     (flag)&&(res=-res);
17     #undef num
18     return res;
19 }
20 const int N=2005;typedef int arr[N];
21 int head[N],Next[N],ver[N],tot;
22 inline void add(int u,int v){
23     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
24 }
25 int hc[N],nc[N],vc[N],tc;
26 inline void addc(int u,int v){
27     vc[++tc]=v,nc[tc]=hc[u],hc[u]=tc;
28 }
29 int n,m,top,cnt,num;arr vis,dfn,low,c,k,st,w,v,d,wc,vv,ins;
30 int dp[N][N];
31 void tarjan(int u){
32     dfn[u]=low[u]=++num,st[++top]=u,vis[u]=1,ins[u]=1;
33     for(int i=head[u];i;i=Next[i]){
34         int v=ver[i];
35         if(!dfn[v]){
36             tarjan(v),cmin(low[u],low[v]);
37         }else if(ins[v]) cmin(low[u],dfn[v]);
38     }
39     if(dfn[u]==low[u]){
40         int y;++cnt;
41         do{
42             y=st[top--],c[y]=cnt,wc[cnt]+=w[y],vv[cnt]+=v[y],ins[y]=0;
43         }while(u!=y);
44     }
45 }
46 void dfs(int u){
47     for(int i=wc[u];i<=m;++i) dp[u][i]=vv[u];
48     for(int i=hc[u];i;i=nc[i]){
49         int v=vc[i];dfs(v);
50         for(int j=m-wc[u];j>=0;--j) for(int q=0;q<=j;++q)
51         cmax(dp[u][j+wc[u]],dp[v][q]+dp[u][j+wc[u]-q]);
52     }
53 }
54 int main(){
55 //    freopen("testdata.in","r",stdin);
56     n=read(),m=read();
57     for(int i=1;i<=n;++i) w[i]=read();
58     for(int i=1;i<=n;++i) v[i]=read();
59     for(int i=1,fa;i<=n;++i)
60     add(fa=read(),i);
61     for(int i=1;i<=n;++i)
62     if(!vis[i]) tarjan(i);
63     for(int u=1;u<=n;++u)
64     for(int i=head[u];i;i=Next[i])
65     if(c[u]!=c[ver[i]]) addc(c[u],c[ver[i]]),++k[c[ver[i]]];
66     for(int i=1;i<=cnt;++i)
67     if(!k[i]) addc(0,i);
68     dfs(0);
69     printf("%d\n",dp[0][m]);
70     return 0;
71 }

 

posted @ 2018-10-08 20:14  bztMinamoto  阅读(174)  评论(0编辑  收藏  举报
Live2D