點此看題面
大致題意:在一棵樹中有n
nn條邊連線n+1
n+1n+
1個節點,現在已知這棵樹上的m
mm個節點,要求封住最少的節點,使這m
mm個節點中的任意乙個節點無法到達葉子節點,若能辦到輸出最少封住的節點數,若不能輸出−1-1
−1。這道題目的正解是樹形dpdp
dp(h
l666
hl666
hl66
6大佬說用o(n
2m
)o(n^2m)
o(n2m)
的最小割也可以過這道題,不過這篇部落格並不討論這種做法,他能做出來是因為他是常數之神)。
樹形dpdp
dp,一般都將狀態由子節點向父節點轉移,這題當然也不例外。
我們可以用f
ff陣列來儲存每乙個節點的狀態:
若f [i
]=
0f[i]=0
f[i]=0
,則說明該節點已被完全封死,相當於既不可能有犯人到達這裡,也不可能從這裡到達出口。
若f [i
]=
1f[i]=1
f[i]=1
,則說明可以從這個節點到達葉子節點。
若f [i
]=
2f[i]=2
f[i]=2
,則說明有犯人可以到達該節點。
每一次轉移,我們可以用乙個s陣列來統計當前節點的子節點中f[s
on[i
]]
f[son[i]]
f[son[
i]]分別為0,1
,2
0,1,2
0,1,
2的次數,並依次進行分類討論:
若當前節點有犯人,則需要在該節點的子節點中的每個可以到達葉子節點的節點上安排乙個警衛。且f[x
]=
2f[x]=2
f[x]=2
(當前節點上有犯人,所以犯人可以到達該節點)。
若既有犯人可以到達該節點的某個子節點,又可以通過該節點的某個子節點到達葉子節點,這說明有犯人可以通過該節點逃出監獄,則需在這個節點安排乙個警衛。且f[x
]=
0f[x]=0
f[x]=0
(當前節點安排了警衛,所以被完全封死)。
否則,如果該節點的某個子節點可以到達葉子節點,則說明該節點也可以到達葉子節點,因此f[x
]=
1f[x]=1
f[x]=1
。否則,如果有犯人可以到達該節點的某個子節點,則說明犯人也可以到達該節點,因此f[x
]=
2f[x]=2
f[x]=2
。如果以上情況皆不滿足,這說明該節點是葉節點或其子節點全被封死,則特判其為葉子節點的情況,若其不是葉子節點則f[x
]=
0f[x]=0
f[x]=0
。既然這樣,就很容易進行動態規劃了,具體**如下:
**
#include
#define n 100000
using
namespace std;
int n,m,ee=
0,ans,a[n+5]
=,lnk[n+5]
=,out[n+5]
=,f[n+5]
=;struct edgee[2
*n+5];
inline
chartc(
)inline
void
read
(int
&x)inline
void
write
(int x)
inline
void
add(
int x,
int y)
,lnk[x]
=ee,
++out[x];}
inline
voiddp(
int x,
int lst)
//具體的dp過程
intmain()
for(i=
1;i<=n;
++i)if(
!(out[i]^1
))(fst==-1
?fst=i:0)
,f[i]=1
;//將葉子節點的狀態初始化為1
dp(fst,0)
;//從乙個葉子節點開始dp
return
write
(f[fst]==2
?ans+
1:ans),0
;//特判該節點為2,即犯人可以到達的情況,由於當前節點是葉子節點,所以要在當前節點在安排乙個警衛,答案加1
}
51nod 1299 監獄逃離 樹形DP
傳送門 51nod 1299 題意 中 思路 dp i 表示警察全部放置完成後i節點的狀態 0 表示逃犯不能到達i節點並且i節點能 經由其子樹 到達出口 不經過警察的情況下 1 表示逃犯不能到達i節點並且i節點不能 經由其子樹 到達出口 不經過警察的情況下 2 表示逃犯能到達i節點並且i節點不能 經...
51nod 1299 監獄逃離
監獄有n條道路連線n 1個交點,編號0至n,整個監獄被這些道路連在一起 任何2點之間都有道路 人們通過道路在交點之間走來走去。其中的一些交點只有一條路連線,這些點是監獄的出口。在各個交點中有m個點住著犯人 m n 1 剩下的點可以安排警衛,有警衛把守的地方犯人無法通過。給出整個監獄的道路情況,以及犯...
51Nod 1299 監獄逃離
這其實是一道樹形dp的神仙題。然後開始推推推,1 hour later樣例都過不了 然後仔細一看題目,貌似像乙個最小割模型,然後5min想了想建圖 首先拆點,將每個點拆成進和出兩個,然後連邊,邊權即為 1 表示割掉這條邊的代價 然後設超級源 s 讓 s 向所有犯人的出點 因為犯人的點無法割去 連邊,...