zoukankan      html  css  js  c++  java
  • bzoj 1812

    什么鬼noip互测题...

    这题很显然是树形dp,但设计状态以及转移是个难点

    记状态f[i][j][k]表示以i为根节点的子树,离i最近的祖宗节点编号为j放了虫洞(伐木场?),i的子树内放了k个伐木场的方案数

    设to为i的某个子节点,当i不放伐木场时,有:

    dp[i][j][k]=min(dp[to][j][k-c]+dp[i][j][c])

    当i放伐木场时,有:

    dp[i][i][k]=min(dp[to][i][k-c]+dp[i][i]c])

    最后合并:

    dp[i][j][k]+=num[i]*dis[i][j]

    dp[i][j][k]=min(dp[i][j][k],dp[i][i][k])

    其中dis[i][j]表示从i到j(j为i的某个祖先节点)的距离,可以预处理出来

    特别的,当i为叶节点(即i没有子节点)时,dp[i][j][0]=dis[i][j]*num[i]直接赋值

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    using namespace std;
    int dp[205][205][55];
    struct Edge
    {
        int next;
        int to;
    }edge[205];
    int head[205];
    int dis[205][205];
    int num[205];
    int f[205];
    int n,k;
    int cnt=1;
    void init()
    {
        memset(head,-1,sizeof(head));
        memset(f,-1,sizeof(f));
        cnt=1;
    }
    void add(int l,int r)
    {
        edge[cnt].next=head[l];
        edge[cnt].to=r;
        head[l]=cnt++;
    }
    void initdfs(int x)
    {
        if(x)
        {
            for(int i=f[x];i!=-1;i=f[i])
            {
                dis[x][i]=dis[x][f[x]]+dis[f[x]][i];
            }
            dis[x][0]=dis[x][f[x]]+dis[f[x]][0];
        }
        for(int i=head[x];i!=-1;i=edge[i].next)
        {
            int to=edge[i].to;
            initdfs(to);
        }
    }
    void dfs(int x)
    {
        if(head[x]==-1)
        {
            for(int i=f[x];i!=-1;i=f[i])
            {
                dp[x][i][0]=dis[x][i]*num[x];
            }
            return;
        }
        if(x)
        {
            dp[x][x][0]=0x3f3f3f3f;
        }
        for(int i=head[x];i!=-1;i=edge[i].next)
        {
            int to=edge[i].to;
            dfs(to);
            for(int j=f[x];j!=-1;j=f[j])
            {
                for(int t=k;t>=0;t--)
                {
                    int temp=0x3f3f3f3f;
                    for(int c=0;c<=t;c++)
                    {
                        temp=min(temp,dp[x][j][c]+dp[to][j][t-c]);
                    }
                    dp[x][j][t]=temp;
                }
            }
            for(int j=k;j>=0;j--)
            {
                int temp=0x3f3f3f3f;
                for(int c=(x!=0);c<=j;c++)
                {
                    temp=min(temp,dp[x][x][c]+dp[to][x][j-c]);
                }
                dp[x][x][j]=temp;
            }
        }
        for(int i=f[x];i!=-1;i=f[i])
        {
            for(int j=0;j<=k;j++)
            {
                dp[x][i][j]+=dis[x][i]*num[x];
                dp[x][i][j]=min(dp[x][i][j],dp[x][x][j]);
            }
        }
    }
    inline int read()
    {
        int f=1,x=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int main()
    {
    //    freopen("girls.in","r",stdin);
    //    freopen("girls.out","w",stdout);
        n=read(),k=read();
        init();
        f[0]=-1;
        for(int i=1;i<=n;i++)
        {
            int v;
            num[i]=read(),f[i]=read(),v=read();
            dis[i][f[i]]=v;
            add(f[i],i);    
        }
        initdfs(0);
        dfs(0);
        printf("%d
    ",dp[0][0][k]);
        return 0;
    }
  • 相关阅读:
    NPOI创建DOCX常用操作
    【Python】django多对多 查询 ,反查等操作
    【Python】python 普通继承方式和super继承方式
    【云计算】开源装机自动化系统 CloudBoot OSInstall 介绍
    【Python】Python AES 对称加密示例
    【Python】Django 如何直接返回404 被 curl,wget 捕获到
    【Python】Django 支持 restful 风格 url
    【Python】Django 聚合 Count与Sum用法,注意点
    【Python】使用 boto 调用 S3 对象存储API
    【Other】千字文 硬笔 楷书 字帖
  • 原文地址:https://www.cnblogs.com/zhangleo/p/9756498.html
Copyright © 2011-2022 走看看