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; }