题目链接:
题目大意:
每个人有一个直接的领导,1是总裁,现在要找一个最大的集合,每个领导领导的人的数量都是偶数,问最大的值是多少。
题目分析:
- 定义状态 dp[u][i] 为以点u为根节点的子树的选取的点的个数是奇数或偶数且合法的最大的权值和。
- 为了保证合法,那么被选取每个点所选取的孩子的所在子树的点的个数之和一定是偶数。
- 如果某个点不选取,那么可以它的孩子为根的子树和为奇数的状态。
- 得到如下的转移方程: dp[u][0]=∑v∈Childmax(dp[v][1]+dp[u][1],dp[v][0]+dp[u][0]) dp[u][1]=max{dp[u][0]+au,∑v∈Childmax(dp[v][1]+dp[u][0],dp[v][0]+dp[u][1])}
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#define MAX 200007
#define INF (1<<29)
using namespace std;
typedef long long LL;
int n;
int a[MAX];
LL dp[MAX][2];
vector<int> e[MAX];
void add ( int u , int v )
{
e[u].push_back ( v );
}
void dfs ( int u )
{
if ( !e[u].size())
{
dp[u][1] = a[u];
dp[u][0] = 0;
return;
}
dp[u][1] = -INF;
dp[u][0] = 0;
LL t1,t0;
for ( int i = 0 ; i < e[u].size() ; i++ )
{
int v = e[u][i];
dfs ( v );
t1 = dp[u][1];
t0 = dp[u][0];
dp[u][1] = max ( t0 + dp[v][1] , t1 + dp[v][0] );
dp[u][0] = max ( t0 + dp[v][0] , t1 + dp[v][1] );
}
dp[u][1] = max ( dp[u][1] , dp[u][0] + a[u] );
}
int main ( )
{
int x,y;
while ( ~scanf ( "%d" , &n ))
{
for ( int i = 0 ; i < MAX ; i++ )
e[i].clear();
for ( int i = 1 ; i <= n ; i++ )
{
scanf ( "%d%d" , &x , &y );
if ( x != -1 )
add ( x , i );
a[i] = y;
}
dfs ( 1 );
printf ( "%I64d\n" , max ( dp[1][0] , dp[1][1]) );
}
}