自從上次模擬賽後,我決定隔一段時間整理一些揹包優化,可能毫無順序
1.d fs
dfsdf
s的時候儲存鏈的資訊
一道模擬賽題:給定一棵樹,有n
nn各節點,每個節點都有乙個非負權值,對於每條邊,你有0.5
0.50.
5的概率斷掉這條邊,求以1
11為根遍歷的數的權值之和為k
kk的概率(答案對998244353
998244353
998244
353取模)
1
<=n
,k
<
=5000
1 <= n,k <= 5000
1<=n
,k<=5
000直接設dp[
i][j
]dp[i][j]
dp[i][
j]代表以i
ii為根的子樹權值之和為k
kk的概率,這樣dpdp
dp的複雜度是o(n
3)
o(n^3)
o(n3
)那麼怎麼優化呢,我們只需設dp[
i][j
]dp[i][j]
dp[i][
j]為遍歷完以i
ii為根的子樹,權值之和為k
kk的概率
注意,這兩個狀態的不同是第二個狀態也記錄了從1
11走到i
ii的情況(因為遍歷是從1
11開始的)
具體轉移看**即可
#include
#include
#include
#include
using
namespace std;
#define int long long
const
int maxn =
5000
, p =
499122177
, mod =
998244353
;struct whead[maxn + maxn +10]
;int a[maxn +10]
, val[maxn +10]
, size[maxn +10]
, dp[maxn +10]
[maxn+10]
, n, k;
inline
void
add(
int x,
int y,
int i)
inline
intread()
void
dfs(
int x,
int fa)
}signed
main()
dp[1]
[val[1]
]=1;
dfs(1,
0); cout << dp[1]
[k]<< endl;
return0;
}
樹形依賴揹包
問題大意 給出一棵樹,根節點為1,每個點有毒素和收穫。要求毒素不超過給定值的情況下使收穫最大。乙個點的父親節點被選取後這個點才能被選取。首先弄出dfs序,也記錄下每個點其子樹及自身的大小。每個點都能夠被選或不選,如果選了才會考慮它子樹。設f i j 表示dfs序上第i位上的點在其子樹及自身上選取了毒...
樹形揹包總結
目錄 2 有物品大小 3 物品大小為1,有k的限制。二 dfs序上dp 例題1例題2 例題3總結下 樹形揹包,就是說,在樹上選乙個包含根的連通塊,或揹包存在依賴關係 選父才能選子 或者需要知道每個點的子樹中選了多少 通常,我們有兩種方法 我們設 dp i,j 表示在i的子節點中選j個的狀態。在轉移時...
樹形揹包DP
include using namespace std const int n 310,m n 2 int h n ne m v m idx int w n int dp n n int n,m void add int a,int b void dfs int u for int j m j 0 ...