Loading

20210524考试—树 题解

\(link\)

两种做法,树形\(dp\)或者高斯消元

树形\(dp\),其实我考场上想这种做法了,当时认为应该跟小胖守皇宫的状态差不多,就设计了个被谁点亮,结果咋也推不出来式子。
实际上这道题并不关心他是被谁点亮的,我们只需要关心他当前按没按,亮不亮就可以了,我们可以设计出来\(4\)种状态,分别对应按了亮了,按了没亮,没按亮了,没按没亮。
然后式子很好推。
就是在取最值的时候有一个技巧,这个也是树形\(dp\)中常用的。
我们想知道子节点中有偶数个亮的时候和奇数个亮的时候的最小值,这个完全没有必要一个一个枚举。
只需要对每一个子节点都直接要最小值,那么取出来一定是一种情况的答案,只需要记录一个最小的差值,补上就行了

多测不清空,爆零两行泪

code
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <bitset>
#define printf Ruusupuu=printf
#define R register int
#define int long long

using namespace std ;
const int N = 3e2 + 10 ;
const int Inf = 0x3f3f3f3f ;
typedef long long L ;
typedef long double D ;

inline int read(){
	int w = 0 ; bool fg = 0 ; char ch = getchar() ;
	while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
	while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch - '0' ) , ch = getchar() ;
	return fg ? -w : w ;
}

int Ruusupuu , n , x , y , cnt , head [N] , ans , f [N][3] ;
struct E{ int fr , to , next ; } a [N << 1] ;

//0 -> 按,亮  1 -> 不按,亮   2 -> 不按,不亮 

inline void add( int f , int t ){
	a [++ cnt].fr = f ;
	a [cnt].to = t ;
	a [cnt].next = head [f] ;
	head [f] = cnt ;
}	

inline void clear(){
	memset( head , -1 , sizeof( head ) ) ;
	memset( a , 0 , sizeof( a ) ) ;	
	memset( f , 0 , sizeof( f ) ) ;
	cnt = 0 ;
}

void dfs( int x , int fa ){
	int ans = 0 , minn = Inf , t = 0 ;
	for( R i = head [x] ; ~i ; i = a [i].next ){
		int y = a [i].to ; 
		if( y == fa ) continue ;
		dfs( y , x ) ; 
		
		f [x][0] += f [y][2] ;
		
		minn = min ( minn , abs( f [y][0] - f [y][1] ) ) ;										
		if( f [y][0] > f [y][1] ) ans += f [y][1] ; 															
		else ans += f [y][0] , t ++ ;
	} f [x][0] ++ ;
	if( t & 1 ) f [x][1] = ans , f [x][2] = ans + minn ;
	else f [x][1] = ans + minn , f [x][2] = ans ;
}	

void sc(){
	while( scanf( "%lld" , &n ) && n != 0 ){ 
		clear() ;
		for( R i = 1 ; i < n ; i ++ ) x = read() , y = read() , add( x , y ) , add( y , x ) ;
		dfs( 1 , 0 ) ;		
		printf( "%lld\n" , min( f [1][0] , f [1][1] ) ) ;
	}	
}  

signed main(){
	sc() ;
	return 0 ; 
}

高斯消元先咕咕。

posted @ 2021-05-30 17:35  Soresen  阅读(37)  评论(0)    收藏  举报