樹上問題一直是我的乙個難點,逐個解決一下。
注意,這個題意是錯的,正確題意見下方。給定n,p(150),n個點的有根樹,問最少選擇幾個沒有父子關係的節點,使得以這些節點為根的子樹的節點數目之和等於p.
表示
設d p[
i][j
]dp[i][j]
dp[i][
j]表示在節點i
ii及其子樹中,滿足子樹節點數目之和等於j
jj的最少節點數目。
轉移
依次遍歷節點i
ii的所有子節點v
vv,那麼:
d p[
i][j
]=mi
ndp[i][j] = min\
dp[i][
j]=m
in
這裡其實隱藏了一維狀態:這裡實際上是把 i的子d p[
h][i
][j]
dp[h][i][j]
dp[h][
i][j
]表示僅考慮節點i
ii的前h
hh個子節點,滿足子樹節點數目之和等於j
jj的最少節點數目。
為了獲得dp[
i][j
]dp[i][j]
dp[i][
j],相當於把h
hh從1到i
ii的子節點數目迴圈.
節點數目
i的子節點數目
i的子節點數
目 個揹包合併了起來。
邊界
d p[
i][i
的子孫節
點數目]
=1
dp[i][i的子孫節點數目]=1
dp[i][
i的子孫
節點數目
]=1
複雜度
單次揹包合併的複雜度是o(n
2)
o(n^2)
o(n2
),一共需要執行n
nn次揹包合併,總複雜度o(n
3)
o(n^3)
o(n3)
以上的題意全是錯的qwq.
給定n,p(150),n個點的有根樹,問最少切斷幾條邊,可以出現乙個節點數為p的連通支。
按照上面的做法,最後的dp[
root
][p]
dp[root][p]
dp[roo
t][p
]等於出現節點數為n−p
n-pn−
p的且包含根節點的連通支所需要的最少切斷次數。
為了求得每個包含每個節點的連通支,需要做換根dp.
合併起來的揹包顯然是無法拆分的,所以需要維護字首合併與字尾合併,就非常的tuosh.
但實際上,考慮乙個節點作為根,並且不斷掉與它父親的邊,那麼實際上和它父親作為根也沒有區別了。
所以在計算時,只考慮以dp[
i][j
]dp[i][j]
dp[i][
j]仍表示以i
ii為根且與父親不連通的子樹。
狀態表示:dp[
i][j
]dp[i][j]
dp[i][
j]表示以i
ii為根的子樹中剩下j
jj個子節點的最小切斷代價。
狀態轉移:dp[
i][j
]=mi
ndp[i][j]=min\
dp[i][
j]=m
in,其中v
vv是i
ii的子節點;本質是合併揹包。
注意,合併之前i
ii和v
vv之間的連邊是斷的,這個代價被兩個dpdp
dp值分別計算了一次。此時要把它不上,所以需要減2.
狀態邊界:dp[
i][1
]=i的
度數
dp[i][1]=i的度數
dp[i][
1]=i
的度數
注意合併揹包時,j
jj需要逆序列舉(參照01揹包的空間優化),k
kk的列舉順序無所謂。
總結:狀態轉移和邊界的設計要緊貼狀態表示,dp[
i][0
]dp[i][0]
dp[i][
0]不可能存在,應該設成inf而不是0。
無根樹上的dp不一定非要使用換根dp,也可以簡單地想一想根之間的替換性質。
認真讀題
/* littlefall : hello! */
#include
using
namespace std;
using ll =
long
long
;inline
intread()
;const
int m =
160, mod =
1000000007
;vector<
int> edg[m]
;int n, p;
int dp[m]
[m];
//dp[i][j]表示以節點i為根的子樹只留下j個節點的最小代價。
void
dfs(
int u,
int f)
}int
main
(void
)memset
(dp,
0x3f
,sizeof
(dp));
for(
int i=
1; i<=n;
++i)
dp[i][1
]= edg[i]
.size()
;dfs(1
,0);
int ans = mod;
for(
int i=
1; i<=n;
++i)
ans =
min(ans, dp[i]
[p])
;printf
("%d\n"
,ans )
;return0;
}inline
intread()
while
(ch>=
'0'&&ch<=
'9')
return x*f;
}
洛谷 P1272 重建道路
題目描述 一場可怕的 後,人們用n個牲口棚 1 n 150,編號1.n 重建了農夫john的牧場。由於人們沒有時間建設多餘的道路,所以現在從乙個牲口棚到另乙個牲口棚的道路是惟一的。因此,牧場運輸系統可以被構建成一棵樹。john想要知道另一次 會造成多嚴重的破壞。有些道路一旦被毀壞,就會使一棵含有p ...
洛谷 P1272 重建道路
題目描述 一場可怕的 後,人們用n個牲口棚 1 n 150,編號1.n 重建了農夫john的牧場。由於人們沒有時間建設多餘的道路,所以現在從乙個牲口棚到另乙個牲口棚的道路是惟一的。因此,牧場運輸系統可以被構建成一棵樹。john想要知道另一次 會造成多嚴重的破壞。有些道路一旦被毀壞,就會使一棵含有p ...
洛谷P1272 重建道路
一場可怕的 後,人們用n個牲口棚 1 n 150,編號1.n 重建了農夫john的牧場。由於人們沒有時間建設多餘的道路,所以現在從乙個牲口棚到另乙個牲口棚的道路是惟一的。因此,牧場運輸系統可以被構建成一棵樹。john想要知道另一次 會造成多嚴重的破壞。有些道路一旦被毀壞,就會使一棵含有p 1 p n...