題解 士多啤梨(樹上切割)

2022-02-19 21:05:13 字數 1710 閱讀 1702

自述:判斷放進了迴圈,debug了1.5個小時,最後還是請sxk大佬才改出,感謝sxk大佬院子裡有一顆又高又大的士多啤梨樹,士多啤梨樹有n個節點,每個節點都結了乙個士多啤梨,吃掉第i個結點的士多啤梨可以得到ai的營養值,由於士多啤梨可能會壞掉,所以ai可能為負值,也可能為0。

現在要砍掉這顆樹的兩條邊,使樹變成三份,並且使得三份各自士多啤梨營養值的和恰好一樣。請問是否有這樣的方法呢?如果有,請輸出yes,否則輸出no。

第一行乙個數t,表示測試點的個數。

接下來t組:

每組第一行乙個數n,表示結點的個數。

接下來n行,每行兩個數fai和ai,表示第i個結點的父親是fai,第i個結點有營養值為ai的士多啤梨,根節點的fai記為0.

【輸出格式】

輸出t行,如果第t組有解,則輸出yes,否則輸出no26

2 40 5

4 22 1

1 14 2

62 4

0 64 2

2 11 1

這是一道可以體現dp思想的爆搜題,(就是用不到dp的dp題)

對於本題,我們考慮,既然要分成 3 份,那麼對於所有營養值之和不為 3 的倍數的資料,輸出「no」。

這棵樹滿足乙個神奇的性質:只要有子樹大小等於營養值之和/3,那麼這棵子樹可以刪去,且對後面判斷剩下子樹時無後效性(dp思想)。

在這裡給出證明:

在這裡定義 子樹大小等於營養值之和/3 為合法子樹。

對於任意一棵合法的樹,根節點所連的邊下可能直接有一棵合法子樹,也可能是包含了另一顆合法子樹的合法子樹(刪去包含的合法子樹後)。那麼在刪去一顆合法子樹後,剩下的一定可以繼續分出合法子樹。否則全樹不合法。

對於存在大於3個合法子樹的樹,兩最近合法子樹節點之間的營養值之和為 0 ,否則這兩個合法子樹不存在。而這營養值之和為零的一段節點,可以放於相鄰的任意一顆子樹。所以必定可以分出 3 棵合法子樹 。

如不滿足上述條件,顯然無法分割。

證畢。

#includeusing namespace std;

const int maxn = 200005 ;

inline int read()

while(g>='0'&&g<='9')

return s*w;

}int n , t , s , size[ maxn ] , sum[ maxn ] , ccc ;

int tot , nex[ maxn ] , to[ maxn ] , head[ maxn ] ;

void add( int x , int y )

void prepare_()

for( register int i = 1 ; i <= n ; i ++ )sum[ i ] = size[ i ] ;

}void dfs( int u )

if( sum[ u ] == s/3 )sum[ u ] = 0 , ccc++ ;

}int ans_check()

void clear()

void init_()

int main()

dfs( 0 ) ;

ans_check();

clear();

} return 0 ;

}

相信下一次有人看這篇部落格也是我退役的時候了。

如果你喜歡我的文章,請點贊支援,謝謝。

題解 count(樹上切割)

今天考試t1,和我之前寫的一篇叫做士多啤梨的題解有點像 description 求一共有多少種方案可以把一棵樹分成大小相同的幾塊。input 第一行乙個數n,表示數的大小。第二行至第n行,每行兩個數x,y表示x和y之間有一條邊。output 一行,表示方案數。sample input 61 2 2 ...

機房練習賽4 7 分士多啤梨 樹上DP

院子裡有一顆又高又大的士多啤梨樹,士多啤梨樹有n個節點,每個節點都結了乙個士多啤梨,吃掉第i個結點的士多啤梨可以得到ai的營養值,由於士多啤梨可能會壞掉,所以ai可能為負值,也可能為0。現在要砍掉這顆樹的兩條邊,使樹變成三份,並且使得三份各自士多啤梨營養值的和恰好一樣。請問是否有這樣的方法呢?如果有...

樹上染色題解

有一棵點數為n的樹,樹邊有邊權。將m個點染成黑色,並將其他的點染成白色。會獲得黑點兩兩之間的距離和加上白點兩兩之間的距離和的收益。問收益最大值是多少。輸入格式 第一行兩個整數n m。接下來n 1行,每行三個整數a b c,表示有一條樹邊連線a b,長度為c。輸出格式 一行 乙個正整數,表示收益的最大...