1 条题解

  • 0
    @ 2025-9-21 19:41:45

    ffii 连边。然后就形成了一个外向基环树森林。缩点之后树形 DP,只有选了 uu 才能选 uu 的儿子。

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=105;
    int n,m,c[N],h[N],dfn[N],low[N],times,bel[N],cnt,C[N],H[N],ind[N],ins[N],dp[N][505],vis[N];
    vector<int>G[N],g[N];
    stack<int>s;
    void Tarjan(int u) {
    	dfn[u]=low[u]=++times,s.push(u),ins[u]=1;
    	for(auto v:G[u]) if(!dfn[v])Tarjan(v),low[u]=min(low[u],low[v]); else if(ins[v])low[u]=min(low[u],dfn[v]);
    	if(dfn[u]==low[u]) {
    		++cnt; int v;
    		do { v=s.top(),s.pop(),ins[v]=0;
    			bel[v]=cnt; C[cnt]+=c[v],H[cnt]+=h[v];
    		} while(u!=v);
    	}
    }
    void DP(int u) {
    	for(int i=C[u]; i<=m; i++) dp[u][i]=H[u];
    	vis[u]=1;
    	for(auto v:g[u]) if(!vis[v]) {
    		DP(v);
    		for(int i=m; i>=C[u]; --i)for(int j=0; j<=i; ++j)if(i-j>=C[u]) dp[u][i]=max(dp[u][i],dp[u][i-j]+dp[v][j]);
    	}
    }
    signed main() {
    	std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    	cin>>n>>m;
    	for(int i=1; i<=n; ++i)cin>>c[i];
    	for(int i=1; i<=n; ++i)cin>>h[i];
    	for(int i=1,f; i<=n; ++i) {
    		cin>>f;
    		if(f)G[f].push_back(i);
    	}
    	for(int i=1; i<=n; ++i) if(!dfn[i]) Tarjan(i);
    	for(int u=1; u<=n; ++u) for(auto v:G[u]) if(bel[u]!=bel[v]) g[bel[u]].push_back(bel[v]),++ind[bel[v]];
    	for(int i=1; i<=cnt; ++i) if(ind[i]==0) g[0].push_back(i);
    	DP(0);
    	cout<<dp[0][m]<<"\n";
    	return 0;
    }
    
    • 1

    信息

    ID
    409
    时间
    1000ms
    内存
    256MiB
    难度
    9
    标签
    (无)
    递交数
    17
    已通过
    2
    上传者