POJ 1192 最优连通子集【树形DP】

题意: 在一个树中找出权值和最大的一个连通子集。

分析: 和 1463 几乎一样的题, 状态转移方程

           // dp[i][0] 以i 为根节点不包含 i 的值 
          // dp[i][1]  以i 为根节点包含 i   的值
          // dp[i][0]=max(dp[j][1],dp[j][0])
          // dp[i][1]+=min(dp[j][0],dp[j][1])    j 为 i 的儿子

View Code
#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
struct node
{
    int x,y,w;
}p[1002];
int abs(int x)
{ return x>0?x:-x; }
bool ok(int i,int j)
{
    if(abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y)==1)
        return true;
    return false;
}
struct tn
{
    int to,next;
}e[100000];
int tot;
int head[1002];
void add(int s,int u)
{
    e[tot].to=u;
    e[tot].next=head[s];
    head[s]=tot++;
}
bool v[1002];
int dp[1002][2];
void dfs(int r)
{
    int j,k;
    dp[r][0]=0;
    dp[r][1]=p[r].w;
    v[r]=true;
    for(j=head[r];j;j=e[j].next)
    {
        k=e[j].to;
        if(!v[k])
        {
            dfs(k);
            if(dp[k][0]>dp[r][0])
                dp[r][0]=dp[k][0];    
            if(dp[k][1]>dp[r][0])      
                dp[r][0]=dp[k][1];
            if(dp[k][1]>0)          
                dp[r][1]+=dp[k][1];
        }
    }
}

int main()
{
    int n,i,j;
    while(scanf("%d",&n)!=EOF)
    {
        tot=1;
        clr(head);
        clr(v);
        clr(dp);
        for(i=0;i<n;i++)
            scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].w);
        for(i=0;i<n;i++)
            for(j=i+1;j<n;j++)
                if(ok(i,j))
                {
                    add(i,j);
                    add(j,i);
                }
        dfs(0);
        printf("%d\n",dp[0][1]>dp[0][0]?dp[0][1]:dp[0][0]);
    }
    return 0;
}

 

 

 

posted @ 2012-07-17 19:28  'wind  阅读(510)  评论(0编辑  收藏  举报