洛谷P2014 选课
传送门啦
一个树上dp(树上背包问题),我用了两个方法,都A掉了,这个题数据可能太水了,第一次打错了都A了,不过错误已经改掉了。
第一次就是用的树上背包,差不多是裸题了吧。
$ f[i][j] $ 表示以 $ i $ 为根的子树中选 $ j $ 个的最优方案,因为我们建立了一个虚点,所以最后用了 $ f[0][m+1]
$
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 305;
inline int read(){
char ch = getchar();
int f = 1 ,x = 0;
while(ch > '9' || ch < '0'){if(ch == '-')f = -1;ch = getchar();}
while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + ch - '0';ch = getchar();}
return x * f;
}
int n,m,u,w[maxn];
int head[maxn],tot;
int f[maxn][maxn],size[maxn];
struct Edge{
int from,to,next,val;
}edge[maxn << 1];
void add(int u,int v){
edge[++tot].from = u;
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot;
}
void dfs(int x,int fa){
size[x] = 1;
f[x][1] = w[x];
for(int i=head[x];i;i=edge[i].next){
int v = edge[i].to;
if(v != fa){
dfs(v , x);
size[x] += size[v];
for(int j=size[x];j>=2;j--)
for(int k=0;k<=size[v];k++)
if(j > k)
f[x][j] = max(f[x][j] , f[x][j-k] + f[v][k]);
}
}
}
int main(){
n = read(); m = read();
for(int i=1;i<=n;i++){
u = read(); w[i] = read();
add(u , i); add(i , u);
}
dfs(0 , -1);
printf("%d\n",f[0][m+1]);
return 0;
}
这个 $ dfs $ 是以 $ x $ 为根,还剩下 $ t $ 个课程可以选,这个 $ f $ 数组没有包含根节点,所以最后没有用 $ m + 1 $ .
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 305;
inline int read(){
char ch = getchar();
int f = 1 ,x = 0;
while(ch > '9' || ch < '0'){if(ch == '-')f = -1;ch = getchar();}
while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + ch - '0';ch = getchar();}
return x * f;
}
int n,m,u,w[maxn];
int head[maxn],tot;
int f[maxn][maxn];
struct Edge{
int from,to,next;
}edge[maxn << 1];
void add(int u,int v){
edge[++tot].from = u;
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot;
}
void dfs(int x,int t){
if(t == 0) return ;
for(int i=head[x];i;i=edge[i].next){
int v = edge[i].to;
for(int k=0;k<=t;k++)
f[v][k] = f[x][k] + w[v];
dfs(v , t - 1);
for(int k=1;k<=t;k++)
f[x][k] = max(f[x][k] , f[v][k-1]);
}
}
int main(){
n = read(); m = read();
for(int i=1;i<=n;i++){
u = read(); w[i] = read();
add(u , i);
}
dfs(0 , m);
printf("%d\n",f[0][m]);
return 0;
}
顺风不浪,逆风不怂。