問題描述
有一棵 n 個節點的樹,樹上每個節點都有乙個正整數權值。如果乙個點被選擇了,那麼在樹上和它相鄰的點都不能被選擇。求選出的點的權值和最大是多少?
輸入格式
第一行包含乙個整數 n 。
接下來的一行包含 n 個正整數,第 i 個正整數代表點 i 的權值。
接下來一共 n-1 行,每行描述樹上的一條邊。
輸出格式
輸出乙個整數,代表選出的點的權值和的最大值。
樣例輸入
51 2 3 4 5
1 21 3
2 42 5
樣例輸出
12樣例說明
選擇3、4、5號點,權值和為 3+4+5 = 12 。
思路:
我們看完這道題後就知道有點和沒有上司的舞台相似,但是他是個無向圖,所以我們需要儲存樹時要同時把2點都儲存進去,那麼我們需要考慮的就是如何去遍歷樹?我們的解題方案也就是樹形動態規劃了!
我們首先建立乙個dp[i][2] dp[i][1]表示 當這個點選擇後的值 dp[i][0]表示 當這個點沒有選擇後的值
然後先把每個點的取值儲存到dp[i][1]裡面。(dp[k][1] = k點權值;)
因為圖的儲存有很多方法,在這個我用的是鄰接表,不知道怎麼用的可以去網上查下圖的儲存。我們儲存時要注意要儲存當時的2個節點的位置因為他是無向圖。
因為他是無向圖我們需要防止他死迴圈,所以我們當父節點的子節點的子節點還是父節點的話我們就不讓他進入函式運算。
我們知道當本節點擊擇後他的樹上和它相鄰的點都不能被選擇所以我們轉移方程就是:
dp[x][1]+=dp[z1][0]
那當他沒有選擇本節點就是: dp[x][0]+=max(dp[z1][1],dp[z1][0]) 可以和他子節點擊擇時和沒有選擇時比較大小然後我們去最大的乙個即可。 z1是x的子節點。(資料跑不完遞迴上線了)
程式:
n=
int(
input()
)dp=[[
0for i in
range(2
)]for i in
range
(n+2)]
#初始化
p=list
(map
(int
,input()
.split())
)#儲存取值
for i in
range
(len
(p))
: dp[i+1]
[1]=p[i]
#儲存權值到對應dp裡面t=1
h=[0for i in
range(2
*n+2
)] z=[
0for i in
range(2
*n+2)]
nx=[
0for i in
range(2
*n+2)]
for i in
range
(n-1):
#儲存無向圖
a=list
(map
(int
,input()
.split())
)# 輸入的值
z[t]
=a[1
]#當a[1]為父節點儲存
nx[t]
=h[a[0]
] h[a[0]
]=tt+=
1 z[t]
=a[0
]#當a[0]為父節點儲存
nx[t]
=h[a[1]
] h[a[1]
]=tt+=
1def
dfs(x,pre):#
k=h[x]
#子節點的編號
while k!=0:
#是否還有子節點
z1=z[k]
#子節點
if pre==z1:
#判斷是否是死迴圈
k=nx[k]
#下個子節點
continue
dfs(z1,x)
#讓zi當父節點進行遞迴
dp[x][1
]+=dp[z1][0
]#當父節點擊擇 我們子節點一定不可以選擇
dp[x][0
]+=max(dp[z1][1
],dp[z1][0
])#當父節點不選擇我們就可以 (選擇子節點或者不選擇子節點)我們取最大值即可
k=nx[k]
#下個子節點
dfs(1,
-1)#找了根節點1來遍歷
print
(max
(dp[1]
[1],dp[1]
[0])
)#看選擇當前節點最大還是不選擇最大
試題 演算法訓練 結點選擇
資源限制 時間限制 1.0s 記憶體限制 256.0mb 問題描述 有一棵 n 個節點的樹,樹上每個節點都有乙個正整數權值。如果乙個點被選擇了,那麼在樹上和它相鄰的點都不能被選擇。求選出的點的權值和最大是多少?輸入格式 第一行包含乙個整數 n 接下來的一行包含 n 個正整數,第 i 個正整數代表點 ...
演算法訓練 結點選擇
演算法訓練 結點選擇 動態規劃 2017.3.29 問題描述 有一棵 n 個節點的樹,樹上每個節點都有乙個正整數權值。如果乙個點被選擇了,那麼在樹上和它相鄰的點都不能被選擇。求選出的點的權值和最大是多少?輸入格式 第一行包含乙個整數 n 接下來的一行包含 n 個正整數,第 i 個正整數代表點 i 的...
演算法訓練 結點選擇
問題描述 有一棵 n 個節點的樹,樹上每個節點都有乙個正整數權值。如果乙個點被選擇了,那麼在樹上和它相鄰的點都不能被選擇。求選出的點的權值和最大是多少?輸入格式 第一行包含乙個整數 n 接下來的一行包含 n 個正整數,第 i 個正整數代表點 i 的權值。接下來一共 n 1 行,每行描述樹上的一條邊。...