洛谷:P1122 最大子树和(dp,)

题目:

在这里插入图片描述

分析:每一个节点都可以当作树的根,至少保留该根最大值问题求解节点个数次。之前有天平题做过删除指定个数的。这个应该更简单了。

不过这样没法用dp,记忆化搜搜啊!:直接是纯暴力的:

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int m;
vector<vector<int> > vv;//存放子节点 
int A[16005];
int B[16005];//0 用过       -1  没用过 
long long D[16005];
long long f(int x)
{
 B[x]=0;
 D[x]=A[x];
 for(int i=0;i<vv[x].size();i++)
 {
  if(B[vv[x][i]]==0) continue;
  B[vv[x][i]]=0;
  long long c=0;
  D[x]+=max(f(vv[x][i]),c);
  } 
 return D[x];
}
int main()
{
 cin>>m;
 for(int i=1;i<=m;i++) cin>>A[i];
 vector<int> v; 
 for(int i=0;i<=m;i++)
 {
  vv.push_back(v);
 }
 for(int i=1;i<m;i++)
 {
  int a,b;
  cin>>a>>b;
  vv[a].push_back(b);
  vv[b].push_back(a);
 }
 long long maxx=-1;
 for(int i=1;i<=m;i++)
 {
  memset(B,-1,sizeof(B));
  memset(D,-1,sizeof(D));
  B[i]=0;
  maxx=max(maxx,f(i));
 }
 cout<<maxx;
}

看着题解,突然想到,完全没必要啊,中间的过程就可以求出来了。很好!我描述不清,可以想通的。

每一个节点都可以当作树的根

#include<bits/stdc++.h>
using namespace std;
int m;
vector<vector<int> > vv;//存放子节点 
int A[16005];
int B[16005];//0 用过       -1  没用过 
long long D[16005];
long long maxx=-(1<<30);
long long f(int x)
{
 B[x]=0;
 D[x]=A[x];
 for(int i=0;i<vv[x].size();i++)
 {
  if(B[vv[x][i]]==0) continue;
  B[vv[x][i]]=0;
  long long c=0;
  D[x]+=max(f(vv[x][i]),c);
  } 
 maxx=max(maxx,D[x]);
 return D[x];
}
int main()
{
 cin>>m;
 for(int i=1;i<=m;i++) cin>>A[i];
 vector<int> v; 
 for(int i=0;i<=m;i++)
 {
  vv.push_back(v);
 }
 for(int i=1;i<m;i++)
 {
  int a,b;
  cin>>a>>b;
  vv[a].push_back(b);
  vv[b].push_back(a);
 }
 memset(B,-1,sizeof(B));
 memset(D,-1,sizeof(D));
 B[1]=0;
 f(1);
 /*for(int i=1;i<=m;i++)
 {
  memset(B,-1,sizeof(B));
  memset(D,-1,sizeof(D));
  B[i]=0;
  maxx=max(maxx,f(i));
 }*/
 cout<<maxx;
}

猜你喜欢

转载自blog.csdn.net/weixin_42721412/article/details/107820530