1. 程式人生 > >[BZOJ1060][ZJOI2007]時態同步 樹形dp

[BZOJ1060][ZJOI2007]時態同步 樹形dp

節點 sample bits col 通路 ace 所有 長時間 zjoi

Description

  小Q在電子工藝實習課上學習焊接電路板。一塊電路板由若幹個元件組成,我們不妨稱之為節點,並將其用數 字1,2,3….進行標號。電路板的各個節點由若幹不相交的導線相連接,且對於電路板的任何兩個節點,都存在且僅 存在一條通路(通路指連接兩個元件的導線序列)。在電路板上存在一個特殊的元件稱為“激發器”。當激發器工 作後,產生一個激勵電流,通過導線傳向每一個它所連接的節點。而中間節點接收到激勵電流後,得到信息,並將 該激勵電流傳向與它連接並且尚未接收到激勵電流的節點。最終,激烈電流將到達一些“終止節點”——接收激勵 電流之後不再轉發的節點。激勵電流在導線上的傳播是需要花費時間的,對於每條邊e,激勵電流通過它需要的時 間為te,而節點接收到激勵電流後的轉發可以認為是在瞬間完成的。現在這塊電路板要求每一個“終止節點”同時 得到激勵電路——即保持時態同步。由於當前的構造並不符合時態同步的要求,故需要通過改變連接線的構造。目 前小Q有一個道具,使用一次該道具,可以使得激勵電流通過某條連接導線的時間增加一個單位。請問小Q最少使用 多少次道具才可使得所有的“終止節點”時態同步?

Input

  第一行包含一個正整數N,表示電路板中節點的個數。第二行包含一個整數S,為該電路板的激發器的編號。接 下來N-1行,每行三個整數a , b , t。表示該條導線連接節點a與節點b,且激勵電流通過這條導線需要t個單位時 間

Output

  僅包含一個整數V,為小Q最少使用的道具次數

Sample Input

3
1
1 2 1
1 3 3

Sample Output

2

HINT

N ≤ 500000,te ≤ 1000000

Solution

做法:樹形dp

很容易想出來是樹形dp(如果有基礎的話)

式子也不難推

設$f[u]$表示從$u$到以它為根的子樹中的葉子節點的最大距離

轉移方程則為$f[u]=max(f[u],f[son]+e[i].v)$

然後答案就是$\sum f[u]-f[son]-e[i].v$

#include <bits/stdc++.h>

using namespace std ;

#define N 1000010
#define inf 0x3f3f3f3f
#define ll long long
#define int long long

int n , s , fa[ N ] , f[ N ] ;
int head[ N ] , cnt ; 
ll ans = 0 ;
struct node {
    
int to , nxt , v ; }e[ N ] ; //f[i]表示i節點到葉子節點所需要花的最長時間 void ins( int u , int v , int w ) { e[ ++ cnt ].to = v ; e[ cnt ].nxt = head[ u ] ; e[ cnt ].v = w ; head[ u ] = cnt ; } void dfs1( int u ) { for( int i = head[ u ] ; i ; i = e[ i ].nxt ) { if( e[ i ].to == fa[ u ] ) continue ; fa[ e[ i ].to ] = u ; dfs1( e[ i ].to ) ; } } void dfs( int u ) { for( int i = head[ u ] ; i ; i = e[ i ].nxt ) { if( e[ i ].to == fa[ u ] ) continue ; dfs( e[ i ].to ) ; f[ u ] = max( f[ u ] , f[ e[ i ].to ] + e[ i ].v ) ; } for( int i = head[ u ] ; i ; i = e[ i ].nxt ) { if( e[ i ].to != fa[ u ] ) { ans += f[ u ] - f[ e[ i ].to ] - e[ i ].v ; } } } main() { scanf( "%lld%lld" , &n , &s ) ; for( int i = 1 ; i < n ; i ++ ) { int a , b , t ; scanf( "%lld%lld%lld" , &a , &b , &t ) ; ins( a , b , t ) ; ins( b , a , t ) ; } dfs1( s ) ; dfs( s ) ; printf( "%lld" , ans ) ; return 0 ; }

[BZOJ1060][ZJOI2007]時態同步 樹形dp