P2014 [CTSC1997] 选课

 

:::单向边不需要 判断边的fa

:::f[i][j]->i root  i的 选中 j 个的最大值 including i f[i][0]=0;

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
#define ll long long
#define ddd printf("-----------------debug\n");
using namespace std;
const int maxn=3e2+10;

int f[maxn][maxn],siz[maxn];
int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;
int n,m;

void add(int u,int v){
    to[++tot]=v; nxt[tot]=head[u];head[u]=tot;
}

void pre(int u){
    siz[u]=1;
    for(int i=head[u];i;i=nxt[i])
    {
        int v=to[i];
        pre(v);
        siz[u]+=siz[v];
    }
}

void dfs(int u)//+siz  单向边 不需要 judge fa 
{
    for(int i=head[u];i;i=nxt[i])
    {
        int v=to[i];// j=m+1 ,>=0
        dfs(v);
        for(int j=min(siz[u],m+1);j>=0;j--)//多拓展也可以 因为 minn->maxx 
        {
            for(int k=0;k<j;k++) //必须要是 <j 因为 siz[v]<j dp 方程必须按其实际意义递推 不保证 有 意外的影响情况
                f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]);
        }
    }
}
int main()
{
    ios::sync_with_stdio(false); cin.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        int s,k; cin>>k>>s;
        add(k,i); f[i][1]=s;
    }
    pre(0);
    //for(int i=0;i<=n;i++) cout<<i<<"->"<<siz[i]<<endl;
    dfs(0);
    cout<<f[0][m+1]<<'\n';// root==0
    return 0;
}
View Code

 


 
 

 

 
posted @ 2023-08-12 23:21  JMXZ  阅读(8)  评论(0)    收藏  举报