洛谷P2014 選課
阿新 • • 發佈:2018-10-30
.org add clu sin etc i++ con inline 有用
傳送門啦
一個樹上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; }
洛谷P2014 選課