hdu 1520 树形dp
来源:互联网 发布:淘宝详情页思路 编辑:程序博客网 时间:2024/06/07 05:46
题目:点击打开链接
题意:每个节点有权值,子节点和父节点不能同时选,问最后能选的最大价值是多少?
分析:这题一看到首先想到的是贪心,就是选间隔的层次的点,可是仔细想想这样是不对的,假如说选了第一层,那么肯定不能选第二层,那么这时候选第三层一定是最优的吗?显然不对,有可能不选第三层而选第四层,所以思路逐渐地清晰。用f[i][0]表示没选这个点,f[i][1]表示选了这个点,那么状态战役方程就很明显了:
f[u][0]+=max(f[v][0],f[v][1]);//其中u是v的父节点,没选u,对于v来说可选可不选 f[u][1]+=f[v][0]; //选了u,对于v来说一定不选
有了状态转移方程,dfs从叶子向根转移,最后就求出整棵树的最大值了。
#include <cstdio>#include <cmath>#include <string>#include <cstring>#include <iostream>using namespace std;const int N=6005;struct edge{ int v; int next;}e[N<<1];int head[N];int f[N][2];int val[N],in[N];//节点权值,节点入度int cnt;void init(){ memset(in,0,sizeof(in)); memset(head,-1,sizeof(head)); cnt=0;}void add_edge(int u,int v) //建立有向图u->v{ e[cnt].v=v; e[cnt].next=head[u]; head[u]=cnt++;}int dfs(int u){ f[u][0]=0; f[u][1]=val[u]; for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; dfs(v); f[u][0]+=max(f[v][0],f[v][1]); f[u][1]+=f[v][0]; } return max(f[u][0],f[u][1]);}int main(){ int n,v,u; //freopen("f.txt","r",stdin); while(~scanf("%d",&n)){ init(); for(int i=1;i<=n;i++){ scanf("%d",&val[i]); } while(scanf("%d%d",&v,&u)&&(v+u)){ add_edge(u,v); in[v]++; } int ans=0; for(int i=1;i<=n;i++){ if(!in[i]){ ans+=dfs(i); } } printf("%d\n",ans); } return 0;}
还有的是建立的无向图,也可以:http://www.cnblogs.com/kuangbin/archive/2012/08/28/2659716.html
仔细读了遍原题,It means that the supervisor relation forms a tree rooted at the rector V. E. Tretyakov. 发现这是一整棵树,所以只有一个树根,只找到树根dfs一遍就可以了,用vector就挺简单的。
#include<stdio.h>#include<string.h>#include<iostream>#include<vector>#include<algorithm>using namespace std;const int MAXN=6050;vector<int>vec[MAXN];int f[MAXN];int hap[MAXN];int dp[MAXN][2];void dfs(int root){ int len=vec[root].size(); dp[root][1]=hap[root];// for(int i=0;i<len;i++)// dfs(vec[root][i]); for(int i=0;i<len;i++) { dfs(vec[root][i]); dp[root][0]+=max(dp[vec[root][i]][1],dp[vec[root][i]][0]); dp[root][1]+=dp[vec[root][i]][0]; }}int main(){ // freopen("f.txt","r",stdin); //freopen("out.txt","w",stdout); int n; int a,b; while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++) { scanf("%d",&hap[i]); vec[i].clear(); f[i]=-1;//树根标记 dp[i][0]=dp[i][1]=0; } while(scanf("%d%d",&a,&b)) { if(a==0&&b==0)break; f[a]=b; vec[b].push_back(a); } a=1; while(f[a]!=-1)a=f[a];//找到树根 dfs(a); printf("%d\n",max(dp[a][1],dp[a][0])); } return 0;}
0 0
- 【树形DP】hdu 1520
- hdu 1520-树形DP
- hdu 1520-树形dp
- hdu 1520 (树形DP)
- hdu 1520 树形DP
- hdu 1520 树形dp
- hdu 1520 (树形)dp
- hdu 1520 树形dp
- HDU 1520 树形dp
- hdu 1520(树形dp)
- HDU 1520 树形dp
- hdu 1520 树形dp入门
- HDU-1520 简单树形dp
- (树形dp) hdu 1520
- hdu 1520 单纯树形dp
- hdu 1520 简单树形dp
- HDU 1520(树形dp)
- hdu 1520 (树形dp)
- Key-Value Observing
- opencv学习笔记(一):基于YCrCb颜色空间的肤色检测
- Java 回顾笔记 1
- hdu 5298 Solid Geometry Homework
- uva1330 - City Game
- hdu 1520 树形dp
- 推导条件随机场参数估计的全过程
- uva1121 - Subsequence
- POJ 3692 Kindergarten(最大独立集)
- UI基础-01第一个iOS应用程序
- 区间问题三部曲(1) : 在线区间最值算法
- 20160212
- 计算机考研的看法
- Linux系统我最常用的20条命令