[HAOI2010]ソフトウェアのインストール[凝縮するポイントツリーDP]

[BZOJ2427] [LuoguP2515]

誰もが依存しているほとんど環縮小tarjanポイントと情報処理リング魏VAを形成することが可能となる点

次いで、0度の点の再接続、従って0ポイント接続の視点をツリーを構成する集

のみこれDPツリーノードの父は選挙への訪問中にその息子を選んだんので、魏最初の[U]〜m個のオードは、[U]をVaに行きます 私はまだ長い時間のための木の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