P1122最大子树和(21.11.3)
Posted 未定_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1122最大子树和(21.11.3)相关的知识,希望对你有一定的参考价值。
P1122最大子树和
题意:一株奇怪的花卉,上面共连有N朵花,共有N-1条枝干将花儿连在一起,并且未修剪时每朵花都不是孤立的。每朵花都有一个“美丽指数”,该数越大说明这朵花越漂亮,也有“美丽指数”为负数的,说明这朵花看着都让人恶心。所谓“修剪”,意为:去掉其中的一条枝条,这样一株花就成了两株,扔掉其中一株。经过一系列“修剪“之后,还剩下最后一株花(也可能是一朵)。要求:通过一系列“修剪”(也可以什么“修剪”都不进行),使剩下的那株(那朵)花卉上所有花朵的“美丽指数”之和最大。
以为只是一个简单的树,做了半天也没思路,看了别人的方法才知道是树形DP,还用到了图里的链式前向星,知识盲区(=_=)。
分析:题意就是求以每个点为根的子树大小,找最大值,用 f[x] 表示以 x 为根且包含 x 的最大权联通块,状态转移方程为f[p]+=max(0,f[k])(k 为p 的儿子,排除负数),求每一个点为根,用dfs实现。
补充: 建树我们用到图的知识。
链式前向星存图如下:u表示结点,h[u]用来定位u的第一条边,t[i].to存u的邻居结点,t[i].next定位u的下一条边指向的邻居结点的位置。例如:u=7时,h[u]=12,即结点7的第一条边连接的邻居结点存在i=12这个位置,t[12].to=6,表示结点7的第一个邻居是结点6,t[12].next=10,即结点7的第二条边连接的邻居结点存在i=10这个位置里,t[10].to=5,即结点7的第二个邻居结点是5,依次类推,直到t[i].next=0时停止。
代码实现:
const int N=16000;
struct n
{
int to,next;
// int w;可以增加一个变量表示结点权值
}t[2*N];
int h[2*N],p=1;
void add(int u,int v)//可加第三个参数int w,即权值
{
t[p].to=v;
//t[p].w=w;
t[p].next=h[u];
h[u]=p++;
}
//遍历结点i的所有邻居
for(int i=h[u];i;i=t[i].next)
{...}
dfs实现过程图解:
只能AC90%的代码
#include<iostream>
#include<algorithm>
using namespace std;
struct n
{
int to,next;
}t[100000];
int p=1,n,a[100000],f[100000],h[100000],x,y,ans=0;
void add(int u,int v)
{
t[p].to=v;
t[p].next=h[u];
h[u]=p++;
}
void dfs(int p,int father)
{
f[p]=a[p];
for(int i=h[p];i;i=t[i].next)
{
int k=t[i].to;
if(k!=father)
{
dfs(k,p);
f[p]+=max(0,f[k]);
}
}
ans=max(ans,f[p]);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n-1;i++)
{
cin>>x>>y;
add(x,y);
add(y,x);
}
dfs(1,0);
cout<<ans<<endl;
}
以上是关于P1122最大子树和(21.11.3)的主要内容,如果未能解决你的问题,请参考以下文章