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