HDU 1520 Anniversary party (简单树形DP)

来源:互联网 发布:织梦cms首页轮播图 编辑:程序博客网 时间:2024/05/19 16:05

此题的建树是一个问题,特别是我还没看清题目,题目中L K  It means that the K-th employee is an immediate supervisor of the L-th employee。。就是告诉我们K是L的根节点。。不过就算没有也没关系,可以判断一下L有没有父节点,如果有就让K成为L的子节点,如果不是,就让K成为L的父节点(都没有父节点也是这样)。

建好树剩下的就不难了(虽然是参考了别人的代码来着)。开一个dp[n][2],dp[n][1]代表选n节点且n节点为根的子树最大和,dp[n][0]代表不选n节点且n节点为根的子树最大和,从底层往上面推就行了,话说不用递归的话我还真不知道怎么写。。

还有我看一些网上代码用vis数组判重,其实根本就没有这个问题,就像后序遍历一样,递归到底才开始算再向上推,不会出现要重复算的情况。

AC代码:

#include<cstdio>#include<ctype.h>#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<stack>#include<cmath>#include<queue>#include<set>#include<ctime>using namespace std;#define NMAX 100005#define ll long longstruct node{    int fa,son,bro;    void init()    {        fa = son = bro = 0;    }}node[6100];int dp[6100][2],a[6100];void dfs(int n){    int k = node[n].son;    while(k)    {        dfs(k);        dp[n][0] += max(dp[k][1],dp[k][0]);        dp[n][1] += dp[k][0];        k = node[k].bro;    }    dp[n][1] += a[n];//    cout<<"n="<<n<<" dp[n][1]="<<dp[n][1]<<" dp[n][0]="<<dp[n][0]<<endl;}int main(){//    freopen("input.txt","r",stdin);//    freopen("o1.txt","w",stdout);    int i,t;    while(~scanf("%d",&t))    {        memset(dp,0,sizeof(dp));        for(i = 1;i <= t; i++)        {            scanf("%d",&a[i]);            node[i].init();        }        int m,n;        while(scanf("%d%d",&m,&n) && m&&n)        {            int k1=m,k2=n;//            if(node[m].fa != 0){k1=n;k2=m;}//没有读清题意,他说了后一个必须是前一个根节点的。//            else{k1=m;k2=n;}//如果不是这样,加上我这2句就可以了。            node[k1].fa = k2;            node[k1].bro = node[k2].son;            node[k2].son = k1;        }        for(i = 1; node[i].fa != 0; i++);        dfs(i);        printf("%d\n",max(dp[i][0],dp[i][1]));    }    return 0;}


0 0
原创粉丝点击