http://poj.org/problem?id=2342
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 4322 | Accepted: 2459 |
Description
Input
Output
Sample Input
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
Sample Output
5
Source
题意:每个人都有个价值,然后每个人不和他的直系上属下属一起,问这样产生的最大价值多少。。
题解:入门级的tree dp,dp[i][0]表示以i为根的子树不选i时产生的最大价值,dp[i][1]表示选i产生的。转移是:
dp[i][0]=sum(max(dp[j][0],dp[j][1]))
dp[i][1]+=sum(dp[j][0]) (i是j的父亲)
边界是dp[i][0]=0,dp[i][1]=value[i].
结果就是max(dp[root][0],dp[root][1])
加的是双向边,这样任选一个作为最开始的root都可以
代码:
/**
* @author neko01
*/
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define pb push_back
#define mp(a,b) make_pair(a,b)
#define clr(a) memset(a,0,sizeof a)
#define clr1(a) memset(a,-1,sizeof a)
#define dbg(a) printf("%d\n",a)
typedef pair<int,int> pp;
const double eps=1e-9;
const double pi=acos(-1.0);
const int INF=0x3f3f3f3f;
const LL inf=(((LL)1)<<61)+5;
const int N=6006;
struct node{
int to,next;
}e[N*2];
int head[N];
int tot;
int dp[N][2];
bool vis[N];
void init()
{
tot=0;
clr1(head);
}
void add(int u,int v)
{
e[tot].to=v;
e[tot].next=head[u];
head[u]=tot++;
}
void dfs(int u)
{
vis[u]=true;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(!vis[v])
{
dfs(v);
dp[u][0]+=max(dp[v][0],dp[v][1]);
dp[u][1]+=dp[v][0];
}
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
init();
for(int i=1;i<=n;i++)
{
scanf("%d",&dp[i][1]);
dp[i][0]=0;
vis[i]=false;
}
int u,v;
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
scanf("%d%d",&u,&v);
dfs(1); //加双向边成无根树任意一点都可以
printf("%d\n",max(dp[1][0],dp[1][1]));
}
return 0;
}poj2342 Anniversary party 简单树形dp
原文:http://blog.csdn.net/neko01/article/details/39941389