首页 > 其他分享 >ICPC Nanjing 2020 M,Monster Hunter做题思路

ICPC Nanjing 2020 M,Monster Hunter做题思路

时间:2022-08-28 15:12:57浏览次数:49  
标签:Monster min int void Hunter read 做题 节点

\(n\) 只有 \(2000\),这样的话我们可以开二维的 dp 了,所以我们大胆一点,定义 \(f_{u,i}\) 表示在 \(u\) 号点,用了 \(i\) 次操作后的代价。

似乎就是一个裸的树上背包了。

考虑一下如何合并,对于 \(u\) 结点,之前的儿子节点已经处理完了,我们现在如何合并到当前的状态。

我们好像要开两个数组,一个 \(f_{u,i}\) 表示 \(u\) 这个节点不用技能的最小代价,而 \(g_{u,i}\) 表示 \(u\) 这个节点用技能的最小代价。这样的话我们就能处理在 \(u\) 节点的合并问题了。我们分别考虑如何转移。

\(f_{u,i}=a_u+\min_{j+k=i}\{\min\{f_{v,j}+a_v,g_{v,j}\}+\min\{f_{u,k},g_{u,k}\}\}\}\)
\(g_{u,i}=\min_{j+k=i-1}\{\min\{f_{v,j},g_{v,j}\}+\min\{f_{u,k},g_{u,k}\}\}\}\)

竟然也靠自己 A 了。树形 dp 还是记得一点的 /se。

#include <bits/stdc++.h>
using namespace std;
template <typename T>inline void read(T& t){t=0; register char ch=getchar(); register int fflag=1;while(!('0'<=ch&&ch<='9')) {if(ch=='-') fflag=-1;ch=getchar();}while(('0'<=ch&&ch<='9')){t=t*10+ch-'0'; ch=getchar();} t*=fflag;}
template <typename T,typename... Args> inline void read(T& t, Args&... args) {read(t);read(args...);}
const int N=2e3+10;

typedef long long ll;
const ll inf=1ll<<60;
int T,fa[N],a[N],sz[N];
ll f[N][N],g[N][N],tmp[N];
vector<int>G[N];

void dfs(int u){
    sz[u]=1;
    g[u][0]=inf;
    for(int v:G[u]){
        dfs(v);
        for(int i=0;i<=sz[u]+sz[v];++i) tmp[i]=inf;
        for(int i=0;i<sz[u];++i)
            for(int j=0;j<=sz[v];++j)
                tmp[i+j]=min(tmp[i+j],f[u][i]+min(f[v][j]+a[v],g[v][j]));
        for(int i=0;i<sz[u]+sz[v];++i) f[u][i]=tmp[i];
        for(int i=0;i<=sz[u]+sz[v];++i) tmp[i]=inf;
        for(int i=1;i<=sz[u];++i)
            for(int j=0;j<=sz[v];++j)
                tmp[i+j]=min(tmp[i+j],g[u][i]+min(f[v][j],g[v][j]));
        for(int i=0;i<sz[u]+sz[v];++i) g[u][i]=tmp[i];
        sz[u]+=sz[v];
    }
    for(int i=0;i<sz[u];++i) f[u][i]+=a[u];
}

int main(){
    read(T);
    while(T--){
        int n;
        read(n);
        for(int i=1;i<=n;++i) G[i].clear();
        for(int i=2;i<=n;++i){
            read(fa[i]);
            G[fa[i]].push_back(i);
        }
        for(int i=1;i<=n;++i) read(a[i]);
        for(int i=0;i<=n;++i) for(int j=0;j<=n;++j) f[i][j]=g[i][j]=0;
        dfs(1);
        for(int i=0;i<=n;++i) printf("%lld ",min(f[1][i],g[1][i]));
        puts("");
    }
    return 0;
}
/*
是谁挥霍的时光啊,是谁苦苦的奢望啊

这不是一个问题,也不需要你的回答

No answer. 
*/

标签:Monster,min,int,void,Hunter,read,做题,节点
From: https://www.cnblogs.com/Mercury-City/p/16632747.html

相关文章

  • 【毒瘤】儒略日 做题笔记
    众所周知:P7075[CSP-S2020]儒略日是一道十分\(EX\)的大模拟作为\(CSP-S\)\(2020\)的\(T1\)远难于\(T2\)。更是有巨佬将过这题的记录放在主页作为自豪的象征。......
  • 【Scan kit】Sechunter针对统一扫码SDK扫出漏洞该如何解决?
    ​1、问题描述项目中集成了华为统一扫码服务SDK,在做送检的准备工作时,针对apk进行了一系列的漏洞扫描处理,其中统一扫码服务SDK在扫描结果中呈现出了少许的漏洞,需要SDK团队......
  • 做题记录
    CF\(\color{#aa00aa}{1900}\sim\color{#ff0000}{2400}\)|AT\(\color{#0000ff}{1600}\sim\color{#c0c000}{2399}\)做题笔记前言准备多刷些这个分数段的CF/AT以涨知......
  • 数论做题记录
    P3811【模板】乘法逆元数据范围是只能\(\mathcal{O}(n)\)过的。考虑递推逆元。设\(t=p/i,k=p%i\)。\(t*i+k\equiv0(\bmodp)\).\(k\equiv-t*......
  • 做题记录:P4013 数字梯形问题
    首先这题是最大费用最大流。然后几乎没什么细节好主意的。遵守以下规则:梯形的第一行有 mm 个数字。从梯形的顶部的 mm 个数字开始在每个数字处可以沿左下或......
  • 做题记录:P2146 [NOI2015] 软件包管理器
    树剖模板题,要求的操作时候区间平推,区间和查询。这还不简单?我会珂朵莉树!然而我打了珂线段树:直接一发A掉。#include<cstdio>#include<algorithm>#include<cmath>#def......
  • 做题记录:P3166 [CQOI2014]数三角形
    题目链接题意:给定 (n+1)(m+1)(n+1)(m+1) 个点的网格图,任意投三个点,求三角形的个数。首先,不考虑三点共线的情况,方案数可以很轻松的得出来。在 (n+1)(m+1)(n+1)(m+1) ......
  • P5677 [GZOI2017]配对统计做题笔记
    一道花了两天的题目,主要是因为死活找不出bug。从树状数组题单里翻出来的,看了第一篇题解。主要思路是把输入的点从小到大排序,统计“好的配对”的数量,统计方法为若当前数和......
  • YbtOJ 做题记录-总集版
    感觉每章都开一篇博客过于占据版面(以及写不动题了想摸一会鱼于是就有了您现在看到的这篇博客。基础算法第1章递推算法第2章贪心算法第3章二分算法图论第2章......
  • CF 做题记录
    CF1360DBuyingShovels*1300link:Problem-1360D-CodeforcesAC:Submission#167227323-CodeforcesCF1338A PoweredAddition*1500link:Problem-1338A-Codefo......