http://codeforces.com/problemset/problem/533/B
题意:
每个人有一个直接的领导,1是总裁,现在要找一个最大的集合,每个领导领导的人的数量都是偶数,问最大的值是多少。
给n,n个人
接下来n行 P,x,pi表示该人领导是pi,X表示该人权值为X
求一个子树(集合),里面所有人的下属的个数和都为偶数,求权值最大的一个集合,输出权值:
一开始方向就走错了。。以为是只需要选根节点U的 偶数个儿子节点(我的意思是偶数条直接分支)便可,没考虑到可以直接选U的孙子节点,这样一来就可以选奇数条直接分支了
(也就是,假设U有三个儿子,我开始以为只能选2个合法的儿子,最后发现可以选两个合法的儿子,并且从第三个儿子的子孙里再选偶数个合法子孙)
所以dp应该用奇偶关系来递推比较好
dp[u][0] 从u往下选偶数个合法后代节点的权值和 (必定不选自身,最后是以u的偶数个合法后代节点构成的森林)
dp[u][1] 从u往下选奇数个各法后代节点的权值和 ( 最后可能是以u为根的一棵树,或奇数个u的合法后代节点构成的森林 )
{
每次递归初始化 dp[x][1]=-8223372036854775807; //第一次dp,实际dp[x][1]不存在,所以设为-inf
int tmp=dp[u][0],tmp2=dp[u][1];
dp[u][0]=max(tmp+dp[v][0],tmp2+dp[v][1]);
dp[u][1]=max(tmp+dp[v][1],tmp2+dp[v][0]);
}
最后 dp[x][1]=max(dp[x][1],dp[x][0]+tm[x]);
答案便是dp[x][1]啦。(比dp[x][0]大)
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const double pi=acos(-1.0);
double eps=0.000001;
int max(int a,int b)
{return a<b?b:a;}
__int64 min(__int64 a,__int64 b)
{return a>b?b:a;}
int max(int a,int b,int c)
{return max(a,max(b,c));}
vector< vector<int> > mp(200005+5);
int tm[200005];
int p;
__int64 dp[200005][2];
void dfs(int x)
{
int i;
dp[x][1]=-8223372036854775807; //第一次dp,实际dp[x][1]不存在,所以设为-inf
for (i=0;i<mp[x].size();i++)
{
int v=mp[x][i];
dfs(v);
__int64 tmp1=dp[x][0],tmp2=dp[x][1];
dp[x][0]=max(tmp1+dp[v][0],tmp2+dp[v][1]);
dp[x][1]=max(tmp2+dp[v][0],tmp1+dp[v][1]);
}
dp[x][1]=max(dp[x][1],dp[x][0]+tm[x]);
}
int n;
int main()
{
cin>>n;
int i;
int hd=-1;
for (i=1;i<=n;i++)
{
scanf("%d%d",&p,&tm[i]);
if (p==-1) {hd=i;continue;}
mp[p].push_back(i);
}
dfs(hd);
printf("%I64d\n",dp[hd][1]);
return 0;
}
第二次写的代码
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const double pi=acos(-1.0);
double eps=0.000001;
vector<int >mp[200005];
__int64 max(__int64 a,__int64 b)
{return a>b?a:b;}
__int64 dp[200005][2];
__int64 aa[200005];
void dfs(int x)
{
int i;
dp[x][0]=0;
dp[x][1]=-200000000005;
for (i=0;i<mp[x].size();i++)
{
int v=mp[x][i];
dfs(v);
__int64 tmp1=dp[x][0],tmp2=dp[x][1];
dp[x][0]=max(tmp1+dp[v][0],tmp2+dp[v][1]);
dp[x][1]=max(tmp2+dp[v][0],tmp1+dp[v][1]);
}
dp[x][1]=max(dp[x][1],dp[x][0]+aa[x]);
}
int main()
{
int n;
cin>>n;
int i,x,y;
int rt=0;
for (i=1;i<=n;i++)
{
scanf("%d%d",&x,&aa[i]);
if (x==-1) rt=i;
else
mp[x].push_back(i);
}
dfs(rt);
printf("%I64d\n",max(dp[rt][0],dp[rt][1]));
return 0;
}