1. 程式人生 > >[BZOJ1907]-樹的路徑覆蓋-樹形DP||貪心

[BZOJ1907]-樹的路徑覆蓋-樹形DP||貪心

說在前面

並沒有什麼想說的,但是要保持格式

題目

題目大意

給出一個N個節點的樹,求出樹的最小路徑覆蓋
路徑不能有公共點,即不能相交

輸入輸出格式

輸入格式:
第一行一個整數T,表示資料組數
對於每組:第一行一個整數N表示點數。接下來N-1行,每行兩個數字u,v描述邊

輸出格式:
每組資料輸出一行一個整數,表示答案

解法

先說DP做法

如果所有點都獨立算作一條路徑,那麼路徑條數為N。在這個基礎之上,每選一條邊去連線兩個度數不為2的節點,相當於合併了兩條鏈,因此條數-1。現在就是需要求最多能選中多少條邊
很顯然的,在任何一種路徑覆蓋方案中,每個點的度數只會是0,1,2。於是定義dp[u][0/1/2]表示只考慮子樹的情況下,u號節點度數為0/1/2時,最多能選多少條邊。然後可以發現dp[u][0]其實就是max(dp[son][0/1/2])之和,而葉結點的dp[u][0]是0,因此度數為0這種情況對最終答案沒有貢獻。然後還可以發現,只有dp[son][0/1]可以轉移到dp[u],而轉移完成之後,dp[son][0/1]就再也用不上了,因此實際上可以把dp[u][0]與dp[u][1]合併。

那麼定義出狀態:dp[u][1/2]表示,u號節點所在鏈沒有終止(度數小於2)/已經終止(度數為2)時,子樹選擇邊數的最大值。轉移是顯然的,分當前點不與子節點連線(度數為0,也就是初值),與一個子節點連線(度數為1),與兩個子節點連線(度數為2)三種情況。細節可以自行思考,很簡單,程式碼也很短

於是貪心做法…

可以發現,當前點如果可以和子節點連線,那麼一定是連線最優,然後直接貪即可

下面是自帶大常數的程式碼

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace
std ; short T , N , tp , head[10005] , dp[10005][3] , fa[10005] ; struct Path{ short pre , to ; }p[20005] ; short size_of_short = sizeof( short ) ; void clear(){ tp = 0 ; memset( head + 1 , 0 , N * size_of_short ) ; } void In( short t1 , short t2 ){ p[++tp].pre = head[t1] ; p[ head[t1] = tp ].to = t2 ; } void
dfs( short u ){ short sum = 0 , tmp = 0 ; for( short i = head[u] ; i ; i = p[i].pre ){ short v = p[i].to ; if( v == fa[u] ) continue ; fa[v] = u , dfs( v ) ; if( dp[v][1] < dp[v][2] ) sum += dp[v][2] ; else{ tmp ++ ; sum += dp[v][1] ; } } dp[u][1] = dp[u][2] = sum ; if( tmp >= 1 ) dp[u][1] ++ ; if( tmp >= 2 ) dp[u][2] += 2 ; } inline void read_( short &x ){ x = 0 ; char ch = getchar() ; while( ch < '0' || ch > '9' ) ch = getchar() ; while( ch >='0' && ch <='9' ) x = (x<<1)+(x<<3)+ch-'0' , ch = getchar() ; } int main(){ scanf( "%hd" , &T ) ; while( T -- ){ scanf( "%hd" , &N ) ; clear() ; for( short i = 1 , u , v ; i < N ; i ++ ){ read_( u ) , read_( v ) ; In( u , v ) ; In( v , u ) ; } dfs( 1 ) ; printf( "%hd\n" , N - max( dp[1][2] , dp[1][1] ) ) ; } }

相關推薦

[BZOJ1907]-路徑覆蓋-樹形DP||貪心

說在前面 並沒有什麼想說的,但是要保持格式 題目 題目大意 給出一個N個節點的樹,求出樹的最小路徑覆蓋 路徑不能有公共點,即不能相交 輸入輸出格式 輸入格式: 第一行一個整數T,表示資料組數 對於每組:第一行一個整數N表示點

bzoj1907路徑覆蓋 樹形dp

scan log print data 狀態 代碼 str 單獨 .com 題目描述 輸入 輸出 樣例輸入 1 7 1 2 2 3 2 4 4 6 5 6 6 7 樣例輸出 3 題解 樹形dp 設f[x]表示以x為根的子樹完成

bzoj1907 路徑覆蓋 樹形dp

Description 給定一棵樹求最小路徑覆蓋 Solution 我們需要用上這是一棵樹的性質。設f[x]表示x為根的子樹內的最小路徑覆蓋且x是一條路徑的端點,g[x]表示x為根的子樹內最小路徑覆蓋且x不是一條路徑的端點。 Code #includ

POJ 1655 BalanceAct 3107 Godfather (的重心)(樹形DP)

hide 可能 scan href == tail cstring get lap 參考網址:http://blog.csdn.net/acdreamers/article/details/16905653 樹的重心的定義: 樹的重心也叫樹的質心。找到一個點,其所有的

【bzoj5123】[Lydsy12月賽]線段的匹配 樹形dp+記憶化搜索

記憶 兩種 spa post mes efi http 搜索 style 題目描述 求一棵 $[1,n]$ 的線段樹的最大匹配數目與方案數。 $n\le 10^{18}$ 題解 樹形dp+記憶化搜索 設 $f[l][r]$ 表示根節點為 $[l,r]$ 的線段

BZOJ.3257.的難題(樹形DP)

cstring log clas pan main efi read logs .com 題目鏈接 狀態只與黑、白兩點的顏色有關,於是用 \(f[x][i][j]\)表示當前以x為根節點,有\(i\)個黑點\(j\)個白點,使得x子樹滿足該條件的最小花費。 最後答案就是 \

COCI2014/2015 Contest#1 D MAFIJA(樹形DP/貪心

題意 給定一個 n n n 個節點的圖,每個點有且僅有一條出邊,選取最多的點使得沒有邊連線相鄰兩個

bzoj 4472: [Jsoi2015]salesman【樹形dp+貪心

一個點,設f[u]為要取最大值顯然是前最大停留次數-1個兒子的正數f和,排個序貪心即可 判重的話就是看沒選的裡面是否有和選了的裡面f值相同的,有的話就是一。注意在選的時候要把加進f的兒子的g合併上去 #include<iostream> #include<cstdio> #inclu

[HNOI2003]消防局的設立 樹形dp // 貪心

https://www.luogu.org/problemnew/show/P2279 一開始就想到了貪心的方法,不過一直覺得不能證明。 貪心的考慮是在深度從深到淺遍歷每個結點的過程中,對於每個沒有覆蓋的結點選擇覆蓋他的祖父結點。 仔細想想覺得這是正確的。 在實現的過程中有一個小技巧是o[i

#bzoj2404#最長鏈(的直徑/樹形DP)

2404: 最長鏈 時間限制: 1 Sec  記憶體限制: 128 MB 題目描述 給定一棵有n個節點的樹,求每個節點到其他節點的最大距離 輸入 輸入第一行是一個自然數n(n≤10000), 接下來 (n−1) 行描述: 第i行包含兩個自然數 , 表示編號

bzoj1907: 路徑覆蓋樹形DP

ret print ... std getc 覆蓋 amp ostream tchar   一眼題...   f[i][0]表示在i連接一個子樹的最小值,f[i][1]表示在i連接兩個子樹的最小值,隨便轉移...   樣例挺強的1A了美滋滋... #inclu

bzoj 1907: 路徑覆蓋貪心+樹形dp

string cpp print names pos else ++ () post 我是在在做網絡流最小路徑覆蓋的時候找到這道題的 然後發現是個貪心+樹形dp \( f[i] \)表示在\( i \)為根的子樹中最少有幾條鏈,\( v[i] \) 表示在\( i \)為根

的最大獨立集,最小點覆蓋,最小支配集 貪心and樹形dp

www 子節點 最大獨立集 com 倒序 最小支配集 交流 屬於 else 目錄 求樹的最大獨立集,最小點覆蓋,最小支配集 三個定義 貪心解法 樹形DP解法 (有任何問題歡迎留言或私聊&&歡迎交流討論哦 求樹的最大獨立集,最小點覆蓋,最小支配集 三個

BZOJ 1907 路徑覆蓋樹形DP

好像可以貪心? f [ i ]

hdu6035 Colorful Tree 樹形dp 給定一棵,每個節點有一個顏色值。定義每條路徑的值為經過的節點的不同顏色數。求所有路徑的值和。

void 題意 iostream cnblogs 編號 emp php scanf http /** 題目:hdu6035 Colorful Tree 鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 題意:給定一棵樹,每

SPOJ 1479 +SPOJ 666 無向最小點覆蓋 ,第二題要方案數,樹形dp

題意:求一顆無向樹的最小點覆蓋。    本來一看是最小點覆蓋,直接一下敲了二分圖求最小割,TLE。          樹形DP,叫的這麼玄乎,本來是線性DP是線上往前\後推,而樹形DP就是在樹上,由葉子結點狀態向根狀態推。  dp[u][1/0]:表示,結點u,1:選擇,0

多叉轉二叉+樹形dp(codevs 1746 貪吃的九頭龍 2002noi)

main bsp 搜索 我們 bre define div 思考 import 題目傳送門 看到這個題目我們要先把問題簡化了,條件中是多叉樹,我們可以把它轉換成二叉樹,左邊是兒子右邊是兄弟的儲存方式。 首先先判斷否的部分,當總的果子小於需求,也就是N-k<M-1時

Codeforces 618D Hamiltonian Spanning Tree(的最小路徑覆蓋)

n) cto 生成 ann 最小路徑 display add alt ext 題意:給出一張完全圖,所有的邊的邊權都是 y,現在給出圖的一個生成樹,將生成樹上的邊的邊權改為 x,求一條距離最短的哈密頓路徑。 先考慮x>=y的情況,那麽應該盡量不走生成樹上的邊,如果

【BZOJ2466】[中山市選2009] 樹形DP

消元 滿足 cpp ret 之前 中山市選 所有 不理解 高斯消元 【BZOJ2466】[中山市選2009]樹 Description 圖論中的樹為一個無環的無向圖。給定一棵樹,每個節點有一盞指示燈和一個按鈕。如果節點的按扭被按了,那麽該節點的燈會從熄滅變為點亮(

Light OJ 1406 Assassin`s Creed 狀態壓縮DP+強連通縮點+最小路徑覆蓋

ret top sizeof set tor pop sni spa sin 題目來源:Light OJ 1406 Assassin`s Creed 題意:有向圖 派出最少的人經過全部的城市 而且每一個人不能走別人走過的地方 思路:最少的的人能夠走全然圖 明顯是