CCF 2019 城市規劃(樹形dp,貢獻)

2021-10-01 05:57:47 字數 2235 閱讀 3573

比較容易想到的一種做法是:設dp[i][j] 表示 i 為根,選 j 個點的答案。在子樹合併時,枚舉子樹選取的點的個數和當前選取的結點個數,加上統計當前這條邊對答案的貢獻更新。

轉移式子為:dp[u][i+j] = min(dp[u][i+j],dp[u][i]+dp[v][j] + i * j * w)

一跑會發現樣例都過不了,原因是這條邊的貢獻只在選的點超過乙個時才會計算,答案必然會漏算某些貢獻。

乙個補救的方法是:另開乙個陣列tp[i][j] 記錄dp[i][j] 取最小值時,選的點到當前i點的距離之和。

轉移方程為:dp[u][i+j] =min(dp[u][i+j],dp[u][i] + dp[v][j] + tp[u][i] * j + tp[v][j] * i + i * j * w

要注意在 dp[u][i+j] 相同的情況下,tp[u][i+j] 要取最小值,因為dp[u][i+j]相同的情況下,顯然tp[u][i]越小對後面的轉移越有利。

一看樣例過了,似乎是一種可行的方案。交上去發現只有30分(還不如暴力打滿40)。

原因是dp轉移式子中,轉移值不只取決於 dp[i][j],還涉及到tp[i][j],而 tp[i][j] 只在 dp[i][j] 盡量小的前提下盡量小。這相當於是在忽略tp[i][j]在轉移中帶來的影響,資料足夠強的話很容易卡掉。

正確的做法是:

還是從貢獻的角度考慮,乙個很明確的思路是,如果在子樹中確定好選的點,產生的新貢獻和當前這條邊權有關。觀察到題目一定有解,並且我們只關注最後的答案。考慮直接用樹形dp維護對最終答案的貢獻。

dp[i][j] 表示 i 為根選 j個結點 對最終答案的貢獻。顯然dp[1][k] 會是正確的答案。

轉移方程為:dp[u][i+j] = min(dp[u][i+j],dp[u][i] + dp[v][j] + w * j * (k - j))

當決定在子樹v中選 j 個點時,最終答案連向這顆子樹的邊權一定會經過 j * (k - j) 次

細算一下複雜度上界是5e8,需要在轉移時加一些剪枝降低上界。

**:

#include

using

namespace std;

const

int maxn =

1e5+10;

#define pii pair

#define fir first

#define sec second

typedef

long

long ll;

vector g[maxn]

;int vis[maxn]

,sum[maxn]

,m,n,k;

ll dp[maxn]

[300

],tmp[

1000];

void

dfs(

int u,

int fa)

dp[u][0

]=0;

if(vis[u]

) sum[u]=1

,dp[u][1

]=0;

for(

auto it : g[u])}

sum[u]

+= sum[it.fir]

;for

(int i =

0; i <=

min(k,sum[u]

); i++)}

}int

main()

for(

int i =

1,u,v,w; i < n; i++

)dfs(1

,0);

printf

("%lld\n"

,dp[1]

[k])

;return0;

}/*5 3 2

1 3 5

1 2 4

1 3 5

1 4 3

4 5 1

11 6 2

2 5 7 8 9 10

1 2 2

1 3 4

2 4 3

2 5 6

3 6 8

3 7 11

4 8 9

6 9 2

6 10 1

7 11 4

*/

CCF 201909 5 城市規劃 樹形dp

題目鏈結 題目大意 思路 u是v的直連父親,先往下搜,向上回溯時,列舉邊計算貢獻,即u和v之間邊w,v裡面選了p個,則all v這一塊選k p個 邊w被經過p k p 次,實際轉移時,考慮v裡取了p個,u在已經搜過的子樹里取了q個,以此來更新dp u p q 的值 dp u p 表示在u這棵子樹 含...

城市規劃道路樹1 3 1版

使用方法 選擇所要合併的樹物件,執行指令碼 說明 將隨機樹高度的指令碼寫到了合併樹的函式中 並且在第一次執行合併樹的指令碼時 執行隨機樹高度的操作 而接下來的合併樹操作中 不再執行 有效的提高了效率 經過測試合併1萬個物件 可以在三分鐘左右完成 因為還不知道maxscript中的time如何操作 沒...

bzoj 3456 城市規劃

題意 求n個點的無向連通圖個數 n個點不同,答案對1004535809取模 n 130000 題解 生成函式的種種神奇應用 不過這玩意真是越來越不oi了 笑 這道題首先考慮遞推公式 設f x 為結點數為x的答案 那麼用總的無向圖數減去不連通的無向圖數目就是答案 f i 2 i i 1 2 f j 2...