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; }

浙公网安备 33010602011771号