zoukankan      html  css  js  c++  java
  • ceoi「chase」

    虽然原题是磁铁,我还是说面包屑吧

    图稍小

    题解

    $70$分$dp$,

    $f_{x,i}$表示走到$x$为止用了$i$次,枚举起点进行转移

    转移$f_{x,i}=max(f_{pre,i},f_{pre,i-1}+sz_{x})$,这里$sz$表示的是儿子的权值和,不包括当前点

    为什么这样转移,考虑你在当前撒下面包屑那么走到任意一个儿子差值都是这些,

    不考虑父亲,在当前撒下面包屑儿子节点鸽子被吸引过来,走到儿子节点旅行家遇到鸽子数量不变,小学生遇到鸽子比旅行家多的就是儿子权值和

    为什么不考虑父亲,父亲的贡献被父亲的父亲考虑了,

     换种方法思考,分为三部分考虑

    1.当前点,这一部分学生和旅行家都走了

    2.自己走的儿子,这一部分学生走了,旅行家走的时候鸽子已经被吸引走了

    3.没走的儿子,这一部分是学生直接多出来的

    关于自己父亲,丢给上面节点考虑就行了,

    $100$分$dp$

    在这里,我先推荐一篇极好的博客

    上面$dp$计算冗余太多,极限就是这些分了

    首先根据上面$dp$经验,放面包屑只会让权值变大,那么这样我们先贪心考虑,放完所有面包屑一定比不放完更优

    发现一段路径一定是由两部分组成的,首先$up$表示从儿子走到当前节点最大贡献,$down$表示从当前点走到子树内最大贡献,

    考虑初始化你不能重复考虑父亲,于是有了

        for(ll i=1;i<=v;i++)
            up[x][i]=sum[x],down[x][i]=sum[x]-val[fa[x]];

    考虑两部分拼接成答案,那么答案就是

            for(ll i=1;i<v;i++) 
                ans=max(up[x][i]+down[y][v-i],ans);

    考虑为什么不是$up[x][i]+down[x][v-i]$好吧,其实挺显然的,

    然后考虑转移,

    $up$从下往上转移所以$-val[y]$,$down$从上往下转移所以$+val[fa[x]]$

    至于为什么要-,跟上面原因类似,你在上面节点计算贡献时已经计算当前点父亲了,你全丢给了父亲以上考虑

    还有很多很多很多细节,我不再一一细说了,

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define A 500000
    ll fa[A],ver[A],nxt[A],head[A],sta[A],val[A],sum[A],up[A][101],down[A][101];
    ll n,ans,tot,v,top;
    void add(ll x,ll y){
        nxt[++tot]=head[x],head[x]=tot,ver[tot]=y;
    }
    void dfs(ll x){
        for(ll i=head[x];i;i=nxt[i]){
            ll y=ver[i];
            if(y==fa[x]) continue ;
            fa[y]=x;
            dfs(y);
        }
        for(ll i=1;i<=v;i++)
            up[x][i]=sum[x],down[x][i]=sum[x]-val[fa[x]];
        for(ll i=head[x];i;i=nxt[i]){
            ll y=ver[i];
            if(y==fa[x]) continue ;
            sta[++top]=y;
            for(ll i=1;i<v;i++) 
                ans=max(up[x][i]+down[y][v-i],ans);
            for(ll i=1;i<=v;i++)
                up[x][i]=max(up[x][i],max(up[y][i-1]+sum[x]-val[y],up[y][i])),
                down[x][i]=max(down[x][i],max(down[y][i-1]+sum[x]-val[fa[x]],down[y][i]));
        }
        ans=max(ans,max(up[x][v],down[x][v]));
        for(ll i=1;i<=v;i++)
            up[x][i]=sum[x],down[x][i]=sum[x]-val[fa[x]];
        while(top){
            ll y=sta[top--];
            for(ll i=1;i<v;i++) 
                ans=max(up[x][i]+down[y][v-i],ans);
            for(ll i=1;i<=v;i++)
                up[x][i]=max(up[x][i],max(up[y][i-1]+sum[x]-val[y],up[y][i])),
                down[x][i]=max(down[x][i],max(down[y][i-1]+sum[x]-val[fa[x]],down[y][i]));
        }
        ans=max(ans,max(up[x][v],down[x][v]));
    }
    int main(){
        scanf("%lld%lld",&n,&v);
        for(ll i=1;i<=n;i++)
            scanf("%lld",&val[i]);
        for(ll i=1,a,b;i<n;i++){
            scanf("%lld%lld",&a,&b);
            add(a,b);add(b,a);
            sum[a]+=val[b];
            sum[b]+=val[a];
        }
        dfs(1);
        printf("%lld
    ",ans);
    }
    View Code
  • 相关阅读:
    STL容器list容器API
    STL容器之list基本概念
    STL容器queue的API
    做tab切换时,点击浏览器返回拿不到实时的tab参数,请求不到实时的数据
    v-for渲染出来的列表,要根据不同的状态改变样式,通过给标签添加lang属性完成
    清除每隔5000毫秒请求一次接口的定时器(需求:每当我手动核销电子码,页面上的显示数据要实时更新到)
    ES6数组解构赋值
    es6 var、let、const命令
    canvas计算高度(自定义高度)
    Vue 点击button请求接口,接收不到返回的参数
  • 原文地址:https://www.cnblogs.com/znsbc-13/p/11631879.html
Copyright © 2011-2022 走看看