zoukankan      html  css  js  c++  java
  • Luogu【[HNOI/AHOI2018]道路】

    在网上翻了几篇博客没看懂,自己强行开码,于是就写篇博客希望对别的“走投无路”的人有所帮助

    心路历程:

    普及+的题目,不知道当时自己在想什么,dp式倒是推对了,然而优化不了空间,惨痛RE,然后钦定HNOI凉凉

    题意:

    设叶子结点到根结点,会经过i条未翻修的公路,j条未翻修的铁路

    则叶子结点到根结点的贡献为(c[i]*(a[i]+i)*(b[i]+j))

    设计方案控制(i,j)使(sum_{叶子结点i}c[i]*(a[i]+i)*(b[i]+j))最小

    Solution

    (f[u][i][j])表示从根结点到结点u经过(i)条未翻修公路,(j)条未翻修铁路

    的贡献最小值

    于是有针对叶子结点(乡村),先预处理出

    [f[u][i][j]=c[u]*(a[u]+i)*(b[u]+j) ]

    然后是城市点(u)

    (u->v)选择修公路时,则右儿子会多经过一条未修的铁路

    [f[u][i][j]=f[lson][i][j]+f[rson][i][j+1] ]

    同理,当(u->v)选择修铁路时,则左儿子会多经过一条未修的公路

    [f[u][i][j]=f[lson][i+1][j]+f[rson][i][j] ]

    所以最终二者取(min)
    (f[u][i][j]=min(f[lson][i][j]+f[rson][i][j+1],f[lson][i+1][j]+f[rson][i][j]);)

    然后是值得注意的细节

    1.(f[u][i][j])(long long),然后中间叶子结点相乘时开1LL

    2.本题卡空间,(f[u][i][j]) 中的一维(u)是不能开到20000的,这显然MLE,但是我们注意到上述dp再处理过程中,是一定先把儿子处理完才处理的自己,又由于这是一颗满二叉树,所以它相当于每次处理一条链,链与链之间的不影响,所以可以定义(dfn[u])表示点在链中映射的结点编号,然后只需要开到80就够了(恐怕这就是这个题目唯一有价值的地方了吧

    最后是激动人心的上代码过程

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    #define ll long long
    #define rg register
    const int _=40100;
    inline int read()
    {
        rg char ch='!';rg int z=1,num=0;
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')z=-1,ch=getchar();
        while(ch<='9'&&ch>='0')num=(num<<3)+(num<<1)+ch-'0',ch=getchar();
        return z*num;
    }
    int n,a[_],b[_],c[_];
    struct ed{int to,next;}e[_<<1];
    vector<int>g[_];
    int cnt,head[_];
    inline void link(int u,int v){e[++cnt]=(ed){v,head[u]};head[u]=cnt;}
    int sz[_],dep[_],dfn[_];
    ll f[105][45][45];
    void dfs(int u,int k)
    {
        dfn[u]=k;
        sz[u]=1;
        for(rg int i=head[u];i;i=e[i].next)
        {
            rg int v=e[i].to;
            dep[v]=dep[u]+1;
            g[u].push_back(v);
            if(g[u][1])dfs(v,k+2);
            else dfs(v,k+1);
            sz[u]+=sz[v];
        }
        if(sz[u]==1)
            for(rg int i=0;i<=dep[u];++i)
                for(rg int j=0;j<=dep[u];++j)
                    f[dfn[u]][i][j]=1ll*c[u]*(a[u]+i)*(b[u]+j);
        else
            for(int i=0;i<=dep[u];++i)
                for(int j=0;j<=dep[u];++j)
                    f[dfn[u]][i][j]=min(f[dfn[g[u][0]]][i][j]+f[dfn[g[u][1]]][i][j+1],f[dfn[g[u][0]]][i+1][j]+f[dfn[g[u][1]]][i][j]);
    }
    int main()
    {
        memset(f,63,sizeof(f));
        n=read();
        for(rg int x,y,i=1;i<n;++i)
        {
            x=read(),y=read();
            if(y<0)link(i,-y+n-1);
            else link(i,y);
            if(x<0)link(i,-x+n-1);
            else link(i,x);
        }
        for(rg int i=n;i<=2*n-1;++i)a[i]=read(),b[i]=read(),c[i]=read();
        dep[1]=0;dfs(1,0);
        printf("%lld
    ",f[dfn[1]][0][0]);
        return 0;
    }
    
    
  • 相关阅读:
    Nginx教程(三) Nginx日志管理
    Nginx教程(二) Nginx虚拟主机配置
    官方解析Cookies和Session的区别
    J2EE十三个技术规范
    J2EE十三个规范小结
    tomcat -web.xml里的内容
    tcp协议和udp协议的使用场景
    IntelliJ IDEA创建maven web项目(IDEA新手适用)
    Maven安装与配置
    X86、X64和X86_64区别
  • 原文地址:https://www.cnblogs.com/Zctoylm-cjoier/p/9249358.html
Copyright © 2011-2022 走看看