题意:每个节点有权值,子节点和父节点不能同时选,问最后能选的最大价值是多少
思路:树形DP入门,由于子节点和父节点不能同时选,那么决策其实就一目了然,对于第i个结点,选还是不选。dp[i][0]为不选取第i个结点时候的最大价值,dp[i][1]为选第i结点的最大价值,那么dp[i][0]+=max(dp[j][1],dp[j][0]),不选第i个结点的时候意味着你可能选了j结点,或者j结点也不选,dp[i][1]+=dp[j][0],j选了i就不能选
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <cstdlib> #include <algorithm> #include <vector> #include <map> #include <string> #include <set> #include <ctime> #include <cmath> #include <cctype> using namespace std; #define maxn 6050 #define LL long long int cas=1,T; vector<int> e[maxn]; int f[maxn]; int a[maxn]; int dp[maxn][2]; void dfs(int u) { dp[u][1]=a[u]; for (int i = 0;i<e[u].size();i++) { int v = e[u][i]; dfs(v); dp[u][0]+=max(dp[v][1],dp[v][0]); dp[u][1]+=dp[v][0]; } } int main() { int n; while (scanf("%d",&n)!=EOF) { for (int i = 1;i<=n;i++) { scanf("%d",&a[i]); e[i].clear(); f[i]=-1; dp[i][0]=dp[i][1]=0; } int x,y; while (scanf("%d%d",&x,&y)&&x&&y) { f[x]=y; e[y].push_back(x); } int temp = 1; while (f[temp]!=-1) temp=f[temp]; dfs(temp); printf("%d\n",max(dp[temp][1],dp[temp][0])); } //freopen("in","r",stdin); //scanf("%d",&T); //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC); return 0; }
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