结点选择

来源:互联网 发布:喜欢 知乎 编辑:程序博客网 时间:2024/04/27 20:34
问题描述

有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少?

输入格式

第一行包含一个整数 n 。

接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。

接下来一共 n-1 行,每行描述树上的一条边。

输出格式
输出一个整数,代表选出的点的权值和的最大值。
样例输入
5
1 2 3 4 5
1 2
1 3
2 4
2 5
样例输出
12
样例说明
选择3、4、5号点,权值和为 3+4+5 = 12 。
数据规模与约定

对于20%的数据, n <= 20。

对于50%的数据, n <= 1000。

对于100%的数据, n <= 100000。

权值均为不超过1000的正整数。



代码如下:

#include "stdio.h"#define MAX 100010#define max(a,b) a>b?a:bstruct tnode{int son[2];int indegree;}tnode[MAX];void DFS(int x,int dp[MAX][2],int weight[MAX]);int main(){int n,i,a,b,root;int weight[MAX]={0},dp[MAX][2]={0};scanf("%d",&n);for(i=1;i<=n;i++)//初始化树节点{scanf("%d",&weight[i]);tnode[i].son[0]=-1;tnode[i].son[1]=-1;tnode[i].indegree=0;}for(i=0;i<n-1;i++)//建树{scanf("%d%d",&a,&b);if(tnode[a].son[0] == -1)tnode[a].son[0] = b;elsetnode[a].son[1] = b;tnode[b].indegree++;}for(i=1;i<=n;i++)//寻找根节点if(! tnode[i].indegree)root=i;DFS(root,dp,weight);//利用dfs原理printf("%d\n",max(dp[root][0],dp[root][1]));return 0;}void DFS(int x,int dp[MAX][2],int weight[MAX]){int i,son;dp[x][1]=weight[x];for(i=0;i<2;i++){son=tnode[x].son[i];if(son == -1)continue;DFS(son,dp,weight);dp[x][0]+=max(dp[son][1],dp[son][0]);dp[x][1]+=dp[son][0];}}
dp[x][0]不取该结点的最大值  dp[x][1]取该结点的最大值

根据题目中,对于每一个结点都存在两种取与不取
1.取结点x,dp[x][1]=weight[x];
那么对其孩子结点只能不取这一种情况dp[x][1]+=dp[son][0];
2.如果不取结点x,对于孩子结点有两种选择就是(取dp[son][1]与不取dp[son][0],当dp[x][0]加上肯定是两者之间最大值)
dp[x][0] += max ( dp[son][0] , dp[son][1]) ;

0 0