(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
题意:HDUPOJ
原题目描述再最下面。
裸题:给你一颗树,每个点有权值,求独立集的最大权值。(每个点不能和它的父节点同时存在)
思路:
直接搜索,记录dp[i][0]
和dp[i][1]
分别表示 不取 和 取 此节点的最大权值和。
转移方程:
dp[i][1] = val[i] + ∑dp[j][0]
- - j 属于 son[i]
dp[i][0] = 0 + ∑max(dp[j][0], dp[j][1])
- - j 属于 son[i]
AC代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#define pb push_back
using namespace std;
typedef long long LL;
const int N = 6e3+7;
const int INF = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
int n, ans;
int val[N], in[N];
int dp[N][2];
vector<int> mp[N];
void dfs(int u){
int len = mp[u].size();
dp[u][1] = val[u];
for(int i = 0; i < len; ++i){
int v = mp[u][i];
dfs(v);
dp[u][1] += dp[v][0];
dp[u][0] += max(dp[v][1], dp[v][0]);
}
}
void init(){
for(int i = 0; i <= n; ++i){
mp[i].clear();
}
memset(dp, 0, sizeof(dp));
memset(in, 0, sizeof(in));
ans = 0;
}
int main(int argc, char const *argv[]){
while(~scanf("%d", &n)){
init();
for(int i = 1; i <= n; ++i){
scanf("%d", &val[i]);
}
for(int i = 1, u, v; i <= n; ++i){
scanf("%d%d", &u, &v);
if(u+v == 0)break;
mp[v].pb(u);
in[u]++;
}
for(int i = 1; i <= n; ++i){
if(in[i] == 0){
dfs(i);
ans = max(dp[i][0], dp[i][1]);
break;
}
}
printf("%d\n", ans);
}
return 0;
}