您的位置:首页 > 其它

BZOJ4726 [POI2017][Sabota?] 树形DP

2017-10-18 21:56 351 查看

状态:

f [u] 表示 u 不叛变的最小 x 值

方程:

f [u] = max { min ( f [v] , size [v] / ( size [u] - 1 ) ) }

解释方程:

1.为什么取max?

—–因为 f [v] 表示的是 v 结点的最小答案,f [u] 不能比 f [v] 小。

2.min{ f [v] , size [v] / ( size [u] - 1 } 表示什么?

——表示 v 的两种状态下的值 : 全是叛徒/v没当叛徒

#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 5e5 + 100 ;
double f
, mx;
int sz
;
vector <int> G
;
int n , k ;

void dfs ( int u , int fa ){
sz [u] = 1 ;
for ( int i = 0 ; i < G [u].size () ; ++ i ) {
int v = G [u] [i] ;
if ( v == fa ) continue ;
dfs ( v , u ) ;
sz [u] += sz [v] ;
}
if ( sz [u] == 1 ) f [u] = 1.0 ;
else f [u] = 0.0 ;
for ( int i = 0 ; i < G [u].size () ; ++ i ) {
int v = G [u] [i] ;
if ( v == fa ) continue ;
f [u] = max ( f [u] , min ( f [v] , (double) sz [v] / ( sz [u] - 1 ) ) ) ;
//      printf ( "%d %lf\n" , u , f [u] ) ;
}
if ( sz [u] > k ) mx = max ( mx , f [u] ) ;
}

int main (){
scanf ( "%d%d" , &n , &k ) ;
for ( int i = 2 ; i <= n ; ++ i ){
int x ;
scanf ( "%d" , &x ) ;
G [x].push_back ( i ) ;
}
dfs ( 1 , 0 ) ;
printf ( "%lf" , mx ) ;
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: