题干在这里:https://www.luogu.org/problemnew/show/P1122
本题老师教了我两种方法,和大家分享一下,希望能帮到大家~~~
第一种思路:
由于每两个点之间都有一些联系,我们可以先把两两之间的关系用边的形式储存下来:
- head[x]是表示与x相连的第一个元素的下标
- edge[x].po是表示链头为x
- edge[x].next是表述链头是x,与x相连的元素的下标
- 运作方法:每读入一个数k,就将head[x]转变为k,之后再由edge数组转变下去,这样就将k与整个链连接起来了
动态规划总是要有状态转移方程的,我们用f[x]表示以x为根的最大价值数(其实就是题目中所谓的美丽指数,只不过这个名字太奇怪了。。。)。用g[x]表示以x为根,并且一定要取x的最大价值数
先考虑g[x]的状态转移方程:
value[x]+∑max(0,g[x]);
考虑f[x]是否取x:
如果不取,那么和他相连的子树都可以取,状态转移方程是(其中y具体取值请参看本人的代码):
max(f[y]);
而且一定要求两种情况的最大值!!!并且所有的f[x]d都要附一个足够小的数才行(本蒟蒻在这里卡了一个小时,望大家注意!!!)
当x是根的时候,需要用到它的子树列,用深搜就可以实现。深搜有两个参数:x表示处理的对象,fa表示该对象的父亲(之后是不能再回到fa的!!)
最后献上代码~~~
#include<iostream>
const int maxN=20000;
const int minvalue=-2147483647;
using namespace std;
struct node{
int po,next;
} edge[2*maxN];
int head[maxN],n,a,b,value[maxN],tot,f[maxN],g[maxN];
void insert(int x,int y)
{
edge[++tot].po=y;
edge[tot].next=head[x];
head[x]=tot;
}
void readin()
{
cin>>n;
for(int i=1;i<=n;++i){
cin>>value[i];
}
for(int i=1;i<n;++i){
cin>>a>>b;
insert(a,b);
insert(b,a);
}
}
void dfs(int x,int fa){
f[x]=minvalue;
g[x]=value[x];
int t=head[x];
while (t!=0){
int y=edge[t].po;
if (y!=fa){
dfs(y,x);
f[x]=max(f[x],f[y]);
g[x]+=max(0,g[y]);
}
t=edge[t].next;
}
f[x]=max(f[x],g[x]);
}
int main()
{
readin();
dfs(1,0);
cout<<f[1]<<endl;
return 0;
}
第二种思路:
存储两数关系方法与第一种思路一样,连状态转移方程都一样,就是求最大价值数的方法不同,上面了深搜的方法,将我们需要的状态在需要的时候求出来。
这次的思路是:直接将所有的状态都求出来,再从后往前改变每个父节点的最大价值数,这个可以用宽搜来实现。
最后附上我的代码~~~
#include<iostream>
#include<cstring>
using namespace std;
const int minvalue=-2147483647;
const int maxN=200000;
struct node{
int po,next;
}tree[2*maxN];
int n,head[maxN],a,b,tot,qwq=1;
int value[maxN],f[maxN][2],g[maxN],k[maxN];
bool panduan[maxN];
void insert(int x,int y)
{
tree[++tot].po=y;
tree[tot].next=head[x];
head[x]=tot;
}
void readin()
{
cin>>n;
for(int i=1;i<=n;++i){
cin>>value[i];
g[i]=value[i];
k[i]=minvalue;
}
for(int i=1;i<n;++i){
cin>>a>>b;
insert(a,b);
insert(b,a);
}
}
void bfs()
{
memset(panduan,true,sizeof(panduan));
f[1][0]=1;
int st=1;
while(st<=qwq){
int t=head[f[st][0]];
while(t!=0){
int y=tree[t].po;
if(y!=f[st][1]){
panduan[f[st][0]]=false;
qwq++;
f[qwq][0]=y;
f[qwq][1]=f[st][0];
}
t=tree[t].next;
}
st++;
}
}
void work()
{
for(int i=n;i>=1;--i){
if(panduan[f[i][0]]==true)
k[i]=value[i];
g[f[i][1]]+=max(0,g[f[i][0]]);
k[f[i][1]]=max(k[f[i][1]],k[f[i][0]]);
k[f[i][1]]=max(g[f[i][1]],k[f[i][1]]);
}
}
int main()
{
readin();
bfs();
work();
cout<<k[1]<<endl;
return 0;
}