蓝桥杯--结点选择

          问题描述

有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少?

解题思路:

这题模型是树形动态规划入门题目,

dp[i][0]表示该节点不被选择,dp[i][1]表示该结点被选择。

转移方程为:

dp[u][1]+=dp[v][0];//选择了u结点,则与它邻接的结点不选;

dp[u][0]+=max(dp[v][0],dp[v][1]);不选择u结点,则与它邻接的结点选择结果最大的;

应该特别注意:该题结点数量较大,应该选用邻接表存储边的关系

#include
#include
#define max(a,b) ((a)>(b)?(a):(b))
#define maxn 100010
bool vis[maxn];
int dp[maxn][2];
int father[maxn];
int head[maxn];
int n;
int cnt;
struct Edge
{
	int to,next;
}edge[2*maxn];
void add(int u,int v)
{
	edge[cnt].to=v;
	edge[cnt].next=head[u];
	head[u]=cnt++;
}
void treedp(int u)
{
	vis[u]=1;
	for(int i=head[u];i!=-1;i=edge[i].next)
	{
		int v=edge[i].to;
		if(!vis[v])
		{
			treedp(v);
			dp[u][1]+=dp[v][0];
			dp[u][0]+=max(dp[v][1],dp[v][0]);
		}
	}
}
void init()
{
	cnt=0;
	memset(dp,0,sizeof(dp));
	memset(father,0,sizeof(father));
	memset(vis,0,sizeof(vis));
	memset(head,-1,sizeof(head));
}
int main()
{
	init();
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d",&dp[i][1]);
	int root=0;
	int begin=1;
	for(int i=0;i


你可能感兴趣的:(蓝桥杯--结点选择)