洛谷P4201 設計路線 樹形dp

2021-09-25 02:36:02 字數 3315 閱讀 1648

在乙個n

nn個點m

mm條邊的森林中選擇若干路徑,同時必須保證每個點最多在一條被選路徑上。求所有點到點1的未選路徑之和的最小值以及方案數。

思路來自soo

kesooke

sook

e大佬

顯然這個森林為一棵樹的時候才能滿足所有點都可以到達點1。

所以若m≠n

−1m≠n-1

m̸​=n−

1的話直接輸出兩個−1-1

−1即可。剩下的都是一棵樹的情況。

先考慮如何求第一問的最小值。

因為乙個點為了滿足最多在一條被選路徑上的要求,所以最多有2條與這個點相連的邊被選擇。三種情況如下圖:

這三種情況就分別為沒有與這個點相鄰的邊,有1個和有2個。

設f [x

][i]

f[x][i]

f[x][i

]表示在以x

xx為根的子樹內,有不多於i(0

≤x≤2

)i(0\leq x\leq 2)

i(0≤x≤

2)條選擇的邊與x

xx相鄰的未選路徑之和的最小值。那麼先分開成3種情況討論,然後再取乙個min

minmi

n即可。

f[x][2]=min(max(f[x][2],f[y][2]+1),max(f[x][1],f[y][1]))\\ f[x][1]=min(max(f[x][1],f[y][2]+1),max(f[x][0],f[y][1]))\\ f[x][0]=max(f[x][0],f[y][2]+1)\end\right.

⎩⎨⎧​f[

x][2

]=mi

n(ma

x(f[

x][2

],f[

y][2

]+1)

,max

(f[x

][1]

,f[y

][1]

))f[

x][1

]=mi

n(ma

x(f[

x][1

],f[

y][2

]+1)

,max

(f[x

][0]

,f[y

][1]

))f[

x][0

]=ma

x(f[

x][0

],f[

y][2

]+1)

​主要是討論當有i

ii條邊與根相鄰的情況下子節點有多少條邊相鄰的限制。

當i =0

i=0i=

0時,子節點有多少邊相鄰都沒關係,那就取盡量小的。

當i =1

i=1i=

1時,要分類是否與這個子節點相連的邊被選擇,若被選擇這個子節點就只能有1條邊連出去,否則依然取最小

當i =2

i=2i=

2時和i=1

i=1i=

1時基本一樣,只不過會有兩個子節點需要相鄰。

因為我們設的是「不多於i(0

≤x≤2

)i(0\leq x\leq 2)

i(0≤x≤

2)條選擇的邊」,所以還要有

f[x][1]=min(f[x][1],f[x][0])\\ f[x][2]=min(f[x][2],f[x][1])\end\right.

g[x][j][2]=g[x][j][2]\times g[y][j-1][2]+g[x][j][1]\times g[y][j][1]\\ g[x][j][1]=g[x][j][1]\times g[y][j-1][2]+g[x][j][0]\times g[y][j][1]\\ g[x][j][0]=g[x][j][0]\times g[y][j-1][2]\end\right.

⎩⎨⎧​g[

x][j

][2]

=g[x

][j]

[2]×

g[y]

[j−1

][2]

+g[x

][j]

[1]×

g[y]

[j][

1]g[

x][j

][1]

=g[x

][j]

[1]×

g[y]

[j−1

][2]

+g[x

][j]

[0]×

g[y]

[j][

1]g[

x][j

][0]

=g[x

][j]

[0]×

g[y]

[j−1

][2]

​當i=

0i=0

i=0時,方案數顯然就是每乙個子樹都連兩條邊的方案數之積。

當i =1

i=1i=

1或i=

2i=2

i=2時,方案數就是其中1,2條邊與子節點連線,其他全部為子節點的方案數之積。

其實g

gg的方程和f

ff的方程及其相似。

還是那樣,最終取乙個min

minmi

ng[x][i][1]=g[x][i][1]+g[x][i][0]\\ g[x][i][2]=g[x][i][2]+g[x][i][1]\end\right.

e[n*2]

;void

add(

int from,

int to)

void

dp1(

int x,

int fa)

} f[x][1

]=min(f[x][1

],f[x][0

]); f[x][2

]=min(f[x][2

],f[x][1

]);}

void

dp2(

int x,

int fa)}}

for(

int i=

1;i<=f[1]

[2];i++)}

intmain()

dp1(1,

0);dp2(1

,0);

printf

("%lld\n%lld"

,f[1][

2]-1

,g[1

][f[1]

[2]]

[2])

;return0;

}

洛谷P2014 選課 樹形dp

給出n 300 n leq300 n 30 0個結點,每個結點都有乙個權值,然後一些結點必須只有選了前驅結點這個結點才可以被選。現在最多選m 300 m leq300 m 30 0個結點,求最大權值。實際上這個是乙個森林,但是通過設定乙個權值為0 00的虛點0 00,把所有的沒有前驅的點全部連到這個...

洛谷P2014 選課(樹形DP)

傳送門 難度提高 省選 該題是一道經典的樹形dp題目,基本就是樹形dp的板子題。注意點的解釋參考 為什麼最後兩行要單獨拿出來做呢?for int i s x i 0 i f x i 1 f x i p x 我們回到題面上,父親是兒子的先修課,所以沒有父親時,兒子再多也沒有用,揹包中處理的子樹是不帶根...

洛谷P2607 騎士 樹形dp

思路 首先我們想到可以對相互憎惡的倆個騎士連邊,這樣就得到了乙個圖,有多個連通塊,並且每個連通塊中最多只有乙個環。如果每個連通塊都是一顆樹,那麼這個問題就很簡單 每個節點都是選或者不選。idea1 我想可不可以把這個比樹多一條邊的圖,變成一棵樹來處理,那麼就是要刪掉環上的一條邊。考慮刪掉這條邊 u,...