hdu1520

来源:互联网 发布:html进销存源码 编辑:程序博客网 时间:2024/06/08 01:51

公司开会

题目描述:

公司的员工是一棵树,每个节点有一个值,要求在树中直接相邻有边的两个不能同时来,问最大的点中的权值和是多大

题解:

水题,dp[u][0/1],代表选该点和不选该点时的最大值,然后dp就好了.注意,在u不选的时候,下面的v可以选可以不选,找一个最大的就好了.

重点:

树形dp,多一位定状态.

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <ctype.h>#include <limits.h>#include <cstdlib>#include <algorithm>#include <vector>#include <queue>#include <map>#include <stack>#include <set>#include <bitset>#define CLR(a) memset(a, 0, sizeof(a))#define REP(i, a, b) for(int i = a;i < b;i++)#define REP_D(i, a, b) for(int i = a;i <= b;i++)typedef long long ll;using namespace std;const int maxn = 6e3 + 100;vector<int> G[maxn];int dp[maxn][2], n, rt;int val[maxn], have_fa[maxn];void dfs(int u, int fa){    dp[u][0] = 0;    dp[u][1] = val[u];    REP(i, 0, G[u].size())    {        int v = G[u][i];        if(v!=fa)        {            dfs(v, u);            dp[u][1] = max(dp[u][1], dp[u][1] + dp[v][0]);            dp[u][0] = max(dp[u][0], dp[u][0] + max(dp[v][1], dp[v][0]));//这是重点        }    }}void solve(){    dfs(rt, 0);    printf("%d\n", max(dp[rt][0], dp[rt][1]));}int main(){   // freopen("2Bin.txt", "r", stdin);    //freopen("3Bout.txt", "w", stdout);    while(scanf("%d", &n) != EOF)    {        REP_D(i, 1, n)        {            scanf("%d", &val[i]);            G[i].clear();            have_fa[i] = 0;        }        int a, b;        while(scanf("%d%d", &a, &b))        {            if(a == 0 && b == 0)                break;            G[b].push_back(a);            have_fa[a] = 1;        }        REP_D(i, 1, n)        {            if(have_fa[i]==0)            {                rt = i;                break;            }        }        solve();    }    return 0;}
0 0
原创粉丝点击