[HAOI2010]软件安装[缩点 树形dp]

[BZOJ2427] [luoguP2515]

每个人都至多有一个依赖点 所以有可能成环 先tarjan缩点并处理出环的信息wei va

再将缩点后的图重新连接 将入度为0的点和0点连接 这样就构成了一颗树

由此做树形dp 只有父亲节点选了它的儿子才能选 所以在访问进去时先把wei[u]~m都赋为va[u] 我会说我又因为树形dp卡了半天吗

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
const int N=100+5,M=500+5,inf=0x3f3f3f3f,P=19650827;
int n,m,in[N],w[N],val[N],f[N][M];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[N],tot=0;
struct edge{int u,v,nxt;}e[N],E[N];
void add(int u,int v){
    e[++tot]=(edge){u,v,head[u]},head[u]=tot;
}
int idx=0,Bcnt=0,dfn[N],bl[N],low[N],wei[N],va[N];
stack<int>s;bool inst[N];
void tarjan(int u){
    dfn[u]=low[u]=++idx;
    s.push(u),inst[u]=1;
    for(int i=head[u],v;i;i=e[i].nxt){
        v=e[i].v;
        if(!dfn[v]) tarjan(v),low[u]=Min(low[u],low[v]);
        else if(inst[v]&&dfn[v]<low[u]) low[u]=dfn[v];
    }
    if(low[u]==dfn[u]){
        int v;++Bcnt;
        do{
            v=s.top(),s.pop();
            inst[v]=0,bl[v]=Bcnt,wei[Bcnt]+=w[v],va[Bcnt]+=val[v];
        }while(u!=v);
    }
}

int hd[N],tt=0;
void Add(int u,int v){
    E[++tt]=(edge){u,v,hd[u]},hd[u]=tt;
}
void dfs(int u){
    for(int i=wei[u];i<=m;++i) f[u][i]=va[u];
    for(int i=hd[u],v;i;i=E[i].nxt){
        v=E[i].v,dfs(v);
        for(int j=m-wei[u];j>0;--j)
        for(int k=0;k<=j;++k)
        f[u][j+wei[u]]=Max(f[u][j+wei[u]],f[u][j+wei[u]-k]+f[v][k]);
    }
}

int main(){
//  freopen("in2.txt","r",stdin);
    //freopen("xor.out","w",stdout);
    rd(n),rd(m); 
    for(int i=1;i<=n;++i) rd(w[i]);
    for(int i=1;i<=n;++i) rd(val[i]);
    for(int i=1,u;i<=n;++i){
        rd(u);
        if(u) add(u,i);
    }
    for(int i=1;i<=n;++i)
    if(!dfn[i]) tarjan(i);
    for(int i=1;i<=tot;++i)
    if(bl[e[i].u]!=bl[e[i].v]) Add(bl[e[i].u],bl[e[i].v]),++in[bl[e[i].v]];
    for(int i=1;i<=Bcnt;++i) if(!in[i]) Add(0,i);
    memset(f,0,sizeof(f));dfs(0);
    printf("%d",f[0][m]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lxyyyy/p/11390563.html
今日推荐