//poj 2342 树形dp入门
//虽然知道这道题的状态转移方程
// dp[u][0]表示不选u这个节点的happy值
// dp[u][1]表示选u,如此一来
// v表示u的直接下级。
// dp[u][0] = sigma(max(dp[v][0],dp[v][1]));
// u没选,那他的直接下级就有两种选择
// 要么选,要么不选,取个较大值
// dp[u][1] = sigma(dp[v][0]);
// u选了,那他的直接下级就选不了了。
// 可就是做不对,wa了四五发
// 还有就是初始化的时候dp[u][1] = happy[i];
// 因为如果只选这第u个节点,那么值肯定是他本身的值
// 最后看到大牛的做法,原来是没有从
// 根开始。。。瞬间哭了
// 还有就是father[i] = i初始化这个是错的
// 要把这一行删去,又wa了好几发。。。
// 我想:如果开始每个节点都是自己节点的父节点,
// 如果是根的话,那就会每次反复的更新自己的状态
// 这样就会产生一些错误的问题,我的思考是这样
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 8000;
int n;
int dp[maxn][2];
// vector<int> mp[maxn];
int father[maxn];
int happy[maxn];
bool vis[maxn];
int root;
void init(){
memset(dp,0,sizeof(dp));
// for (int i=1;i<=n;i++)
// mp[i].clear();
// for (int i=1;i<=n;i++)//这里加上去就错了。。。
// father[i] = i;
for (int i=1;i<=n;i++){
scanf("%d",&happy[i]);
}
int a,b;
root = 0;
while(scanf("%d%d",&a,&b)!=EOF){
if (!a&&!b)
break;
father[a]=b;
root = b;
}
memset(vis,0,sizeof(vis));
}
void dfs(int u){
//dp[u][0] = 0;
dp[u][1] = happy[u];
vis[u] = true;
for (int i=1;i<=n;i++){
if (!vis[i]&&father[i]==u){
dfs(i);
dp[u][1] +=dp[i][0];
dp[u][0] +=max(dp[i][1],dp[i][0]);
}
}
// return max(dp[u][0],dp[u][1]);
}
void solve(){
dfs(root);
}
void print(){
printf("%d\n",max(dp[root][0],dp[root][1]));
}
int main(){
//freopen("G:\\Code\\1.txt","r",stdin);
int m;
while(scanf("%d",&n)!=EOF){
init();
solve();
print();
}
}
07-20
07-20
07-20
07-20
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交