乙個dfs序的題

2021-08-14 17:54:43 字數 2051 閱讀 1723

一棵樹,每個節點上有di個商品,每個商品費用為ci,價值為wi,然後某個人在這棵樹上買東西,要求買東西的節點是乙個聯通塊。

輸入:輸入第一行乙個正整數t,表示測試資料組數。

對於每組資料,

第一行兩個正整數n;m;

第二行n個非負整數w1,w2...wn;

第三行n個正整數c1,c2...cn;

第四行n個正整數d1,d2...dn;

接下來n-1行每行兩個正整數u;v表示u和v之間有一條道路

輸出:每組資料乙個數表示答案。

考慮乙個暴力,首先列舉每個點必須選,然後以該節點為根,對整棵樹做一遍dfs求出dfs序,然後倒著做,記f[i][j]表示點i的答案,首先如果取點i,那麼就由i的子樹轉移,轉移之後和不取i(當然也不取i的子樹)取max,那麼i的子樹的答案就記在i+1節點上,最後f[1][j(1<=j<=m)]中的最大值取答案,因為這樣轉移的話我們列舉的根一定是會選的。

一開始我想直接樹形dp,但是發現每次轉移需要m^2的時間。

然後我們發現不需要對整棵樹做dfs序,只需要對子樹做就好了,為什麼呢,因為強制選根以及選根上面的點必然會在上面的點當根的時候算上,那麼根據這個性質點分治就好了。

有乙個很重要的細節,就是我做多重揹包是用二進位制分組做的,所以當強制選點i的時候,我們需要另外開乙個陣列,把f[i+1][j]賦值給它,然後如果直接跑揹包的話可能會出現乙個情況,就是不選點i的商品的收益比選點i個更優秀,所以做二進位制分組每個組都強制要選,然後相互間再互相轉移。

#include#include#include#include#includeusing namespace std;

const int maxn = 505;

int first[maxn], next[maxn << 1], go[maxn << 1], t;

int w[maxn], c[maxn], n, m, i, j, k, t, x, y;

int f[maxn][maxn << 3], top[maxn], n, size[maxn], root, big, tot, ans;

int cost[maxn][20], gain[maxn][20], len[maxn], g[20][maxn << 3];

bool vis[maxn];

inline int get()

inline void add(int x, int y)

inline void getroot(int now, int las, int nn)

inline void dfs(int now, int las)

inline void solve(int now)

else

for(j = cost[top[i]][k]; j <= m; j ++)

g[k][j] = max(g[k][j], g[0][j - cost[top[i]][k]] + gain[top[i]][k]);

for(j = cost[top[i]][k]; j <= m; j ++)

g[k][j] = max(g[k][j], g[k - 1][j - cost[top[i]][k]] + gain[top[i]][k]);

} for(j = 0; j <= m; j ++)

f[i][j] = max(g[len[top[i]]][j], f[i + size[top[i]]][j]);

} for(j = 0; j <= m; j ++)

ans = max(ans, f[1][j]);

for(int i = first[now]; i; i = next[i])

if (!vis[go[i]]) }

int main()

if (x) cost[i][++len[i]] = c[i] * x, gain[i][len[i]] = w[i] * x;

} for(i = 1; i < n; i ++)

big = n;

getroot(1, 0, n);

solve(root);

cout << ans << endl;

}}

dfs序入門 CF上的幾道題

由於我太菜了,做了好幾道題終於感覺自己算是入門了 cf 343d 線段樹時間戳 三個操作 1 v 把v和v的所有兒子染色 2 v 把v和v的所有父親取消染色 3 v 查詢某個節點顏色 做法 利用染綠色的性質,如果某個節點在某個時間t1被染綠,在時間t2被取消,那麼當且僅當t1 t2時這個時候他被染色...

BFS的乙個題

關於 bfs要點 1 若為可化為的座標系圖形,可用結構體儲存其x值,y值和步數。一般開now 和 next now用於取出佇列裡面的結構體 next用於上下左右的運動計算,並且push到佇列中。2 在運用佇列時,常用的函式 push,front,size,empty,pop 等等 特別是在front...

乙個簡單的題

problem description 小明今年3歲了,現在他已經能夠認識100以內的非負整數,並且能夠進行100以內的非負整數的加法計算.對於大於等於100的整數,小明僅保留該數的最後兩位進行計算,如果計算結果大於等於100,那麼小明也僅保留計算結果的最後兩位.例如,對於小明來說 1 1234和3...