列表

详情


NC21672. 树上的苹果

描述

有一棵树,标号为0到n-1,0为根节点,每个点有点权
现在你可以在一些点上放苹果,也可以拿掉某些点上的苹果
一个点可以放苹果当且仅当这个点的所有儿子都放上了苹果
如果根节点放上苹果任务完成
求在整个过程中放着苹果的节点的点权之和的最大值的最小值( 也就是说你要选择一个合理的顺序放置苹果来使得答案最优)

输入描述

第一行输入一个整数n (2 ≤ n ≤ 1000)

第二行输入n-1个整数p[0]->p[n-2], p[i]表示(i+1)与p[i]之间有一条边,0 ≤ p[i] ≤ i

第三行输入n个整数表示每个点的点权,1 ≤ w[i] ≤ 105 , w非减

输出描述

输出一个整数

示例1

输入:

5
0 1 2 3
1 2 2 4 4

输出:

8

说明:

{0,1,2,3} //分别表示1的父亲 2的父亲 3的父亲 4的父亲
{1,2,2,4,4}//每个点的点权值
Returns: 8
五个节点构成了一条链
在节点4上放一个石头 (权值和 = 4).
在节点3上放一个石头 (权值和 = 8).
移除节点4上的石头 (权值和 = 4).
在节点2上放一个石头 (权值和 = 6).
在节点1上放一个石头 (权值和 = 8).
移除节点2上的石头 (权值和 = 6)
在节点0(根节点)上放一个石头 (权值和 = 7)
整个过程中最大的权值和为8,不存在比最大值比8小的方案了

示例2

输入:

5
0 0 0 0 
1 2 3 4 5

输出:

15

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 5ms, 内存消耗: 1396K, 提交时间: 2020-04-17 11:08:31

#include <iostream>
#include <cstring>
#include <map>
#include <vector>
#include <climits>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
ll depth[maxn];
ll head[maxn];
ll w[maxn];
struct Edge{
	ll next,to;
}e[maxn<<1];
ll cnt;
ll ans=-100;
ll ding[maxn];
void add(ll x,ll y){
	e[cnt].to=y;
	e[cnt].next=head[x];
	head[x]=cnt++;
}

bool cmp(ll a,ll b){
	return ding[a]+w[b]>ding[b]+w[a];
}

void dfs(ll u,ll fa,ll de){
	vector<int> son;
	for(int i=head[u];~i;i=e[i].next){
		int v=e[i].to;
		if(v==fa) continue;
		dfs(v,u,de+1);
		son.push_back(v);
	}
	if(son.size()==0) {
		ding[u]=w[u];
		return ;
	}
	ll sum=0;
	sort(son.begin(),son.end(),cmp);
	//
	for(int i=0;i<son.size();i++){
		int v=son[i];
		ding[u]=max(ding[u],sum+ding[v]);
		sum+=w[v];
	}
	ding[u]=max(ding[u],sum+w[u]);
	
}

int main()
{
	for(int i=0;i<maxn;i++) head[i]=-1;
	ll n;
	cin>>n;
	for(int i=0;i<n-1;i++){
		ll p;
		cin>>p;
		add(i+1,p);
		add(p,i+1);
	}
	for(int i=0;i<n;i++){
		cin>>w[i];
	}
	dfs(0,-1,0);
	//cout<<"ok"<<endl;
	ll ans=0;
	cout<<ding[0]<<endl; 
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 7ms, 内存消耗: 2808K, 提交时间: 2020-08-21 17:30:43

#include<bits/stdc++.h>
const int maxn=100010; 
int n;
int MU[maxn],ans[maxn];
std::vector<int>son[maxn];
void dfs(const int u);
bool cmp(const int &_a, const int &_b);
int main() {
  scanf("%d", &n);
  for (int i = 2, x; i <= n; ++i) {
    scanf("%d", &x);
      ++x;
    son[x].push_back(i);
  }
  for (int i = 1; i <= n; ++i) {
    scanf("%d", MU + i);
  }
  dfs(1);
  printf("%d\n",ans[1]);
  return 0;
} 
void dfs(const int u) {
  for (auto v : son[u]) {
    dfs(v);
  }
  std::sort(son[u].begin(), son[u].end(), cmp);
  int _ret = 0;
  for (auto v : son[u]) {
    if (_ret >= ans[v]) {
      _ret -= MU[v];
    } else {
      ans[u] += ans[v] - _ret;
      _ret = ans[v] - MU[v];
    }
  }
  ans[u] += std::max(0, MU[u] - _ret);
}
inline bool cmp(const int &_a, const int &_b) {
  return (ans[_a] - MU[_a]) > (ans[_b] - MU[_b]);
}

C++(g++ 7.5.0) 解法, 执行用时: 4ms, 内存消耗: 656K, 提交时间: 2023-07-18 17:17:28

#include<bits/stdc++.h>

#define x first
#define y second
using namespace std;
using i128=__int128;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int,int> PII;
const int N=1010;
vector<int> e[N];
int w[N];
int n;
bool cmp(PII p1,PII p2){
    return p1.x-p1.y>p2.x-p2.y;
}

int dfs(int u){
    vector<PII> sw;
    for(auto v:e[u]){
        sw.push_back({dfs(v),w[v]});
    }
    int maxs=0,val=0;
    sort(sw.begin(),sw.end(),cmp);
    for(auto sval:sw){
        maxs=max(maxs,val+sval.x);
        val+=sval.y;
    }
    return max(val+w[u],maxs);
}

void solve(){
    cin >>n;
    for(int i=1;i<n;i++){
        int v;
        cin >>v;
        e[v].push_back(i);
    }
    for(int i=0;i<n;i++)   cin>>w[i];
    cout <<dfs(0) <<"\n";
}

int main(){
    int t=1;
    //cin >>t;
    while(t--)  solve();
    return 0;
}

上一题