树的最大独立集(1初步)

poj2342


   先预热一下,开始先从这个入手,然后再做poj3342,实质都是一样的。


   题意:输入的前n个单数是每个人的快乐程度,就当做价值吧,后n-1个是关系,最后以0 0 结束关系。求整体价值最大,要求他们每个人的关系不能是直接的上下属,即结点间不相邻。

   注意: 价值 在这题中 有正有负 , 人数是<6000 ,整形sum 计算价值是足够的。


   思想: 是结点对结点的递推,而不会一层对上一层的递推。

        有两个状态,1 .结点u 和 它的子节点的子节点集

                   2 .结点u的子节点集

         (那么就应该用两个空间变量去存储更新)

         由于价值有正有负,要求它的最大值,那么,max()进行更新


         每种状态求得的是  该结点的最大价值,由该节点去推 父节点和父父节点 




#include<stdio.h>
#include<string.h>
#define max(a,b) a>b?a:b
int dp[6001][2],par[6001];

void dfs( int r ,int n)
{
	int i,m;

	
    
	for(i = 1;i <= n ;i++ )
	{
		if(par[i] == r)
		{
			dfs(i , n);

			m =  max(dp[i][0] , dp[i][1]);
			dp[r][0] = max(dp[r][0] , m + dp[r][0]);
			if(par[r]!=0)
			dp[par[r]][1] = max(dp[par[r]][1] , m + dp[par[r]][1]);
		}
	}

}
int main()
{
	int n,i,j;
	int c,f,m,root;
	while(scanf("%d",&n)!=EOF)
	{
		memset(par,0,sizeof(par));
	    memset(dp,0,sizeof(dp));
		for(i= 1 ;i <= n;i++)
		 scanf("%d",&dp[i][1]);

		root = 0;
		for(i= 0;i<n;i++)
		{
			scanf("%d %d", &c ,&f);
			if(c== 0 && f == 0)break;
            par[c] =f;
			if(par[f] == 0)root = f;
		}


		dfs(root , n);

		m =  max(dp[root][0] ,dp[root][1]);

		printf("%d\n",m);	


	}


	return 0;
}

你可能感兴趣的:(c,dp,基础,ACM)