<span style="font-family: 微软雅黑, 黑体, 宋体; background-color: rgb(255, 255, 255);">问题描述</span>
<span style="text-indent: 2em; background-color: rgb(255, 255, 255);"><span style="white-space: pre;"> </span>有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少?</span>
输入格式
第一行包含一个整数 n 。
接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。
接下来一共 n-1 行,每行描述树上的一条边。
输出格式
输出一个整数,代表选出的点的权值和的最大值。
样例输入
5
1 2 3 4 5
1 2
1 3
2 4
2 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的正整数。
节点数目多边少采用邻接表。
dp[i][0]表示该节点不被选择,dp[i][1]表示该结点被选择。
dp[u][1]+=dp[v][0];//选择了u结点,则与它邻接的结点不选。
dp[u][0]+=max(dp[v][0],dp[v][1]);不选择u结点,则与它邻接的结点选择结果最大的。
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
typedef struct node{
int adjvex;
node* next;
}EdgeNode;
typedef struct {
int value;
EdgeNode* firstedge;
}VertexNode;
void add(int a,int b, VertexNode* adjlist){
EdgeNode* node = new EdgeNode;
node->next = adjlist[a-1].firstedge;
node->adjvex = b-1;
adjlist[a-1].firstedge = node;
}
void treedp(int u,VertexNode* adjlist,int** dp,int* vis){
vis[u] = 1;
EdgeNode* p = adjlist[u].firstedge;
while(p){
int v = p->adjvex;
if(!vis[v]){
treedp(v,adjlist,dp,vis);
dp[u][1]+=dp[v][0];
dp[u][0]+=max(dp[v][1],dp[v][0]);
}
p = p->next;
}
}
int main() {
int n;
cin>>n;
VertexNode* adjlist;
adjlist = new VertexNode[n];
for(int i = 0;i<n; i++){
cin>>adjlist[i].value;
adjlist[i].firstedge = NULL;
}
int* father = new int[n+1]();
int root = 0;
for(int i = 0; i<n-1; i++){
int a,b;
cin>>a>>b;
add(a,b,adjlist);
add(b,a,adjlist);
father[b] = a;
root = a;
}
/*
for(int i = 0; i<n; i++){
EdgeNode* p = adjlist[i].firstedge;
cout<<i<<" ";
while(p!=NULL){
cout<<p->adjvex<<" ";
p = p->next;
}
cout<<endl;
}
*/
int** dp = new int*[n];
for(int i = 0;i<n; i++){
dp[i] = new int[2];
dp[i][0] = 0;
dp[i][1] = adjlist[i].value;
}
while(father[root]){
root = father[root];
}
int* vis = new int[n]();
treedp(root-1,adjlist,dp,vis);
cout<<max(dp[root-1][0],dp[root-1][1])<<endl;
return 0;
}