E. Compressed Tree codeforces

树形dp+大模拟
分类讨论出全部情况就行了
ac_code:
中间一些注释掉的一些也是我的推导过程

# include  <bits/stdc++.h>
using  namespace  std ;

using ll = int64_t ;

namespace predefine {
const long long inf = 0x3f3f3f3f3f3f3f3f ;
using Int = __int128 ;
using pll = pair < ll , ll > ;
# define  IOS  iostream::sync_with_stdio ( 0 ) ; cin.tie ( 0 ) ;

# define af( i , a , b ) for ( ll i = a ; i <= b ; ++ i )
# define df( i , a , b ) for ( ll i = a ; i >= b ; -- i )

# define Dg( x ) cout << " ------- " <<  x << " ------- " << '\n'
# define Dged Dg ( "Debug ed" )
# define Dgop Dg ( "Debug op" )
# define pr( x ) cout << #x << " = " << x << '\n'
# define pn putchar ('\n') 
# define ps cout << "yes" 
# define __fin( a ) freopen ( a , "r" , stdin ) 
# define __fout( a ) freopen ( a , "w+" , stdout ) 

# define lowbit( x ) ( x & ( - x ) ) 
}
using namespace predefine ;


//-----  板子  ---------------------------------------------------------------------------------------------------------

//-----  板子  ---------------------------------------------------------------------------------------------------------


ll Pow ( ll a , ll b , ll mod ) { 
	a = a % mod ; ll ans = 1 ; 
	for ( ; b ; b >>= 1 ) { if ( b & 1 ) ans = ( a * ans ) % mod ; a = ( a * a ) % mod ; } 
	return ans ; }

inline ll sum1 ( ll _a ) { return ( _a * ( _a + 1 ) ) >> 1 ; }
inline ll sum2 ( ll _b ) { return _b * ( _b + 1 ) * ( 2 * _b + 1 ) / 6  ; }

ll dx [ 4 ] = { -1 , 0 , 1 , 0 } ;
ll dy [ 4 ] = { 0 , 1 , 0 , -1 } ;

// using ll = long long ;!!!

void solve () {
	ll n ; cin >> n ;
	vector < ll > v ( n ) ;
	af ( i , 0 , n - 1 ) cin >> v [ i ] ;
	vector < vector < ll > > map ( n ) ;
	vector < ll > din ( n ) ;
	af ( i , 2 , n ) {
		ll u , v ; cin >> u >> v ; -- u , -- v ;
		map [ u ].push_back ( v ) ;
		map [ v ].push_back ( u ) ;
		++ din [ v ] ;
		++ din [ u ] ;
	}
	ll ans = 0 ;
	vector < ll > size ( n ) ;
	function < void ( ll , ll ) > dfs = [ & ] ( ll now , ll fa ) {
		ll nmax = -inf , max = -inf , max2 = -inf , cnt = 0 ;
		for ( auto here : map [ now ] ) {
			if ( here == fa ) continue ;
			dfs ( here , now ) ;
			if ( size [ here ] >= 0 ) {
				size [ now ] += size [ here ] ;
				++ cnt ;
			}
			else nmax = std::max ( nmax , size [ here ] ) ;
			if ( size [ here ] >= max2 ) {
				max2 = size [ here ] ;
				if ( max2 >= max ) swap ( max2 , max ) ;
			}
		}
//		cout << "now" << ' ' << now + 1 << endl ;
		// if ( din [ now ] <= 2 ) {
		// 	ans = std::max ( ans , size [ now ] + v [ now ] ) ;
		// }
		// if ( din [ now ] >= 3 ) {
		// 	ans = std::max ( ans , max + max2 ) ;
		// 	ans = std::max ( ans , size [ now ] + v [ now ] ) ;
		// }
		ans = std::max ( { ans , max + max2 ,
			 max + v [ now ] , v [ now ] , 
			 size [ now ] + ( cnt == 2 ? ( std::max ( v [ now ] + nmax , 0ll ) ) : v [ now ] ) } ) ;
//		cout << "size [ now ] " << size [ now ] << " cnt " << cnt << " std::max ( v [ now ] + nmax , 0ll ) " 
//			<< std::max ( v [ now ] + nmax , 0ll ) << " v [ now ] " << v [ now ] << endl ;
		// ans = std::max ( { ans , max + max2 ,
		// 	 size [ now ] + ( cnt == 2 ? ( nmax == inf ? 0 : std::max ( v [ now ] + nmax , 0 ) ) : v [ now ] ) } ) ;
		if ( din [ now ] <= 2 ) 
			size [ now ] = std::max ( max , v [ now ] ) ;
		else {
			if ( v [ now ] >= 0 ) {
				if ( cnt == 0 ) {
					size [ now ] = v [ now ] ;
				}
				else if ( cnt == 1 ) {
//					pr ( v [ now ] ) ;
//					pr ( size [ now ] ) ;
//					if ( nmax + size [ now ] >= 0 ) {
//						size [ now ] = std::max ( { size [ now ] + nmax + v [ now ] , size [ now ] , v [ now ] } ) 
//					}
//					else size [ now ] = std::max ( v [ now ] , size [ now ] ) ;
					size [ now ] = std::max ( { size [ now ] + nmax + v [ now ] , size [ now ] , v [ now ] } ) ;
				}
				else size [ now ] += v [ now ] ;
			}
			else if ( v [ now ] < 0 ) {
				if ( cnt == 0 ) {
//					pr ( max ) ; pr ( v [ now ] ) ;
					size [ now ] = std::max ( max , v [ now ] ) ;
				}
				else if ( cnt == 1 ) {
					size [ now ] = size [ now ] ;
				}
				else size [ now ] = std::max ( size [ now ] + v [ now ] , max ) ;
			}
		}
//		cout << "size [ now ] " << size [ now ] << endl ;
	};
	dfs ( 0 , 0 ) ;
	cout << ans << endl ;
}

int  main () {
	IOS ;
//	__fin ( "in.in" ) ;
	ll _ = 1 ;
	// rd ( _ ) ;
    cin >> _ ;
	while ( _ -- ) {
		solve () ;
	} 
	return 0 ;
}

/*
//-----  数据  ---------------------------------------------------------------------------------------------------------
1
4
2 1 -3 3 
1 2
1 3
1 4

1
5
-3 1 3 -2 3 
1 2
1 3
2 4
2 5

1
28
0 5 -4 -5 -2 -3 2 0 -1 4 -5 5 -4 -1 4 -3 4 -1 -5 5 2 -1 -2 -3 -2 0 -2 -2 
11 20
5 18
16 22
18 12
25 10
23 26
4 9
26 17
26 6
22 19
9 10
23 7
26 24
13 11
15 9
2 20
28 21
22 27
20 1
4 24
16 3
5 28
8 1
10 18
4 1
11 16
14 7
----------
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值