题解:

如果是一个环,那么就是每个点都要

否则就是一个数

然后dp

tarjan强连通+树形dp

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n,m,cnt,last[N],x,last2[N],inq[N],scc,ind,top,v[N];
int w[N],sv[N],sw[N],dfn[N],low[N],belong[N],q[N],f[N][N],in[N];
struct edge
{
    int to,next;
}e[N],ed[N];
void jb(int u,int v)
{
    e[++cnt].to=v;
    e[cnt].next=last[u];
    last[u]=cnt;
}
void jb2(int u,int v)
{
    in[v]=1;
    ed[++cnt].to=v;
    ed[cnt].next=last2[u];
    last2[u]=cnt;
}
void tarjan(int x)
{
    int now=0;
    low[x]=dfn[x]=++ind;
    q[++top]=x;inq[x]=1;
    for (int i=last[x];i;i=e[i].next)
     if (!dfn[e[i].to])
      {
        tarjan(e[i].to);
        low[x]=min(low[x],low[e[i].to]);
      }
     else if(inq[e[i].to])
      low[x]=min(low[x],dfn[e[i].to]);
    if (low[x]==dfn[x])
     {
        scc++;
        while (now!=x)
         {
            now=q[top--];inq[now]=0;
            belong[now]=scc;
            sv[scc]+=v[now];
            sw[scc]+=w[now];
         }
     }
}
void rebuild()
{
    cnt=0;
    for (int x=1;x<=n;x++)
     for (int i=last[x];i;i=e[i].next)
      if (belong[e[i].to]!=belong[x])
       jb2(belong[x],belong[e[i].to]);
}
void dp(int x)
{
    for (int i=last2[x];i;i=ed[i].next)
     {
        dp(ed[i].to);
        for (int j=m-sw[x];j>=0;j--)
         for (int k=0;k<=j;k++)
          f[x][j]=max(f[x][j],f[x][k]+f[ed[i].to][j-k]);    
     }
    for (int j=m;j>=0;j--)
     if (j>=sw[x])f[x][j]=f[x][j-sw[x]]+sv[x];
     else f[x][j]=0;
}
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",&x);
        if (x)jb(x,i);
     }  
    for (int i=1;i<=n;i++)
     if (!dfn[i])tarjan(i);
    rebuild();
    for (int i=1;i<=scc;i++)
     if (!in[i])jb2(scc+1,i);
    dp(scc+1);
    printf("%d\n",f[scc+1][m]);
    return 0;
}

 

posted on 2017-10-28 10:41  宣毅鸣  阅读(166)  评论(0编辑  收藏  举报