ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

(树形dp)Spring tree

2022-06-04 22:32:09  阅读:169  来源: 互联网

标签:ch leaf int Spring tree cin const dp define


题目链接

Spring tree

题目概述

给定n个铁球,重量为wi,再给定n - 1条弹簧(可变的边权)所链接的两端,每个位置上的铁球可以相互交换。弹簧的长度为每个节点的子树边权和+1。问从根节点(1节点)开始的最大深度。

输入 #1

4
1 2 3 4
1 2
2 3
3 4

输出 #1

23

样例说明

In the test case, keep original arrangement is a good idea.
maximum depth = (1+4) + (1+4+3) + (1+4+3+2) = 23

思路

首先我们发现,更重的球会更倾向于放到深度最深的位置。

枚举最优解中深度最深的叶子 leaf,那么最优解会怎样放置呢?

首先最重的球一定给 leaf,然后考虑 leaf 的父亲 parent(leaf),那么最重的 size(parent(leaf)) 个球一定都在 parent(leaf) 的子树中(其中 size(u) 表示 u 的子树大小)..... 依次类推。

对球的重量排序,用 w(k) 表示 k 个最重的球的总重量。

那么我们可以把节点 u 的权值设成 w(size(u)) 接着求出树上从根到树叶找出一条权值和最大的路径即可,这个可以用 O(n) 的 DP 来实现,需要注意的是根节点没有连向父亲的弹簧,所以根节点权值应该设成 0.

AcCode:

// #pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
//#include <ext/rope>
//using namespace __gnu_cxx;
using namespace std;

#define sp ' '
#define endl '\n'

template<typename T> inline T read(){
    T x = 0, f = 0; char ch = cin.get();
    while (!isdigit(ch)) f |= ch=='-', ch = cin.get();
    while (isdigit(ch)) x = x * 10 + (ch ^ 48), ch = cin.get();
    return f ? -x : x;
}
template<typename T> bool chkmin(T &a, T b){return (b < a) ? a = b, 1 : 0;}
template<typename T> bool chkmax(T &a, T b){return (b > a) ? a = b, 1 : 0;}

#define dd(x) cerr << "Line:" << __LINE__ << sp << #x << " -> " << (x) << ", "
#define de1(x) cerr << "Line:" << __LINE__ << sp << #x << " -> " << (x) << endl
#define de2(a, b, x) cerr << "Line:" << __LINE__ << sp << #a << "[" << b << "]" << "->" << x << endl

#define int ll
//#define x first
//#define y second
#define gg exit(0);
#define pb push_back
#define ls (u << 1)
#define rs (u << 1 | 1)
#define eb emplace_back
#define read() read<int>()
#define mod(x) (x + mod) % mod
#define NO cout << "NO" << endl
#define YES cout << "YES" << endl
#define all(x) (x).begin(), (x).end()
#define tmax(a,b,c) (a>b?(a>c?a:c):(b>c?b:c))
#define clar(a, b) memset((a), (b), sizeof(a))
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define fmax(a,b,c,d) (a>b?a:b)>(c>d?c:d)?(a>b?a:b):(c>d?c:d)
#define cdouble(x, a) cout << setprecision(x) << fixed << a << endl

typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> PII;
typedef unsigned long long ull;

const double pi = acos(-1);
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 10;

int n, m, cnt, ans;
int tree[N], siz[N], sum[N];
vi g[N];
vi w;

void dfs1(int u, int fa){
    siz[u] = 1;
    for(auto v : g[u]){
        if(v != fa) dfs1(v, u); 
        siz[u] += siz[v];
    }
}
void dfs2(int u, int fa){
	int res = 0;
	for(auto v : g[u]){
		if(v != fa){
			dfs2(v, u);
			res = max(res, tree[v] + sum[siz[v]] + 1);
		}
	}
	tree[u] = res;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	
    cin >> n;
    rep(i, 1, n){
        int a; cin >> a;
        w.pb(a);
    }
    sort(all(w), greater<int>());
    
    rep(i, 1, n) sum[i] = sum[i - 1] + g[i];

    rep(i, 1, n - 1){
        int u, v; cin >> u >> v;
        g[u].pb(v); g[v].pb(u);
    }
	
    dfs1(1, -1);
    
    dfs2(1, -1);

    cout << tree[1] << endl;
	return 0;
}

标签:ch,leaf,int,Spring,tree,cin,const,dp,define
来源: https://www.cnblogs.com/ReSakura/p/16342946.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有