2200 專項 D 0 1 Tree(樹形dp)

2021-09-22 16:36:06 字數 1680 閱讀 2049

原題:

題意:

給出一棵樹,每條邊有邊權0或1,現在要找出有序對的對數,滿足要求:x到y的路徑不能在遇到1後再遇到0。

解析:

顯然只有四種狀態:從上往下記錄為1、0、10、01,那麼用dp記錄每個點的子樹中,下面的點與之路徑為對應情況的點數。

轉移:

設d p[

p][0

]=0,

dp[p

][1]

=1,d

p[p]

[10]=

2,dp

[p][

01]=3

dp[p][0]=0,dp[p][1]=1,dp[p][10]=2,dp[p][01]=3

dp[p][

0]=0

,dp[

p][1

]=1,

dp[p

][10

]=2,

dp[p

][01

]=3

答案:

首先是子樹每個點到roo

troot

root

的情況,因為0和1雙向,01和10只能單向,所以ans

+=2∗

(dp[

0]+d

p[1]

)+dp

[2]+

dp[3

]ans+=2*(dp[0]+dp[1])+dp[2]+dp[3]

ans+=2

∗(dp

[0]+

dp[1

])+d

p[2]

+dp[

3]。然後是每個子樹中,通過根連線的折線,列舉每個兒子,算一下可以組成的情況就行(若乙個兒子的0的數量為a[0],那麼其他地方0的數量為dp[0]-a[0])。

這裡折線在兩個端點的時候都會算一次,所以要除二。

#include

using

namespace std;

#define pill pair

#define ll long long

const

int maxn=

2e5+5;

vectorv[maxn]

;ll dp[maxn][4

];//下面有多少個點與之為此關係

ll ans;

ll ans1;

void

dfs(

int p,

int fa)

else

dp[p]

[v]++;}

ans+=2

*(dp[p][0

]+dp[p][1

])+dp[p][2

]+dp[p][3

];for(

int i=

0;i.size()

;i++);

if(v==0)

else}}

intmain()

),v[b]

.push_back()

;}dfs(1,

-1);

printf

("%lld\n"

,ans+ans1/2)

;}

2200 專項 B Cubes(stl 模擬)

原題 題意 有m個方塊,每個有座標 x,y x,y x,y 值從0到m 1,這個方塊是穩定的當且僅當 x 1,y 1 x y 1 x 1,y 1 x 1,y 1 x,y 1 x 1,y 1 x 1,y 1 x,y 1 x 1,y 1 存在方塊或者y為0,初始時穩定。你和對手輪流乙個乙個抽出所有方塊,...

app專項測試0 crash

a 作業系統 大量的裝置,各種作業系統,目前使用最多的作業系統有 android ios windows blackberry等等,它們之間的應用軟體互不相容。b 裝置 觸控式和非觸控式裝置 有限的記憶體容量,電池耗電量,螢幕尺寸 解析度等。c 網路 不同的網路和運營商,目前我國的三大運營商就有電信...

徹底搞定0x0d和0x0a

我只在arm linux c和vc 下做了試驗,請大家在接觸其它語言環境下,小心推廣,不行就自己動手做試驗,最可靠。在arm linux c和vc 下回車換行的意義如下。回車 cr ascii碼 r 十六進製制,0x0d,回車的作用只是移動游標至該行的起始位置 換行 lf ascii碼 n 十六進製...