1003: 结点选择
Time Limit: 1 Sec Memory Limit: 128 MB 64bit IO Format: %lldSubmitted: 25 Accepted: 8
[ Submit][ Status][ Web Board]
Description
有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少?
Input
多组测试数据
每组第一行包含一个整数 n 。
接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。
接下来一共 n-1 行,每行描述树上的一条边。
Output
输出一个整数,代表选出的点的权值和的最大值。
Sample Input
5
1 2 3 4 5
1 2
1 3
2 4
2 5
Sample Output
12
HINT
样例说明
选择3、4、5号点,权值和为 3+4+5 = 12 。
数据规模与约定
对于20%的数据, n <= 20。
对于50%的数据, n <= 1000。
对于100%的数据, n <= 100000。
权值均为不超过1000的正整数。
#include <bits/stdc++.h>
#include <iostream>
#include <stdio.h>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
int vis[100009];
int dp[100009][2];
vector<int>v[100009];
int ans;
void dfs(int x)
{
vis[x]=1;
for(int i=0;i<v[x].size();i++)
{
int y=v[x][i];
if(vis[y])continue;
dfs(y);
dp[x][1]+=dp[y][0]; //选父节点那么不选子节点
dp[x][0]+=max(dp[y][0],dp[y][1]);//不选父节点那么选或者不选子节点
}
ans=max(ans,dp[x][0]);
ans=max(ans,dp[x][1]);
}
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0;i<=n;i++)v[i].clear();
memset(vis,0,sizeof vis);
memset(dp,0,sizeof dp);
for(int i=1;i<=n;i++)
{
scanf("%d",&dp[i][1]);
}
int x,y;
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
ans=0;
dfs(1);
printf("%d\n",ans);
}
return 0;
}