zoukankan      html  css  js  c++  java
  • BZOJ 4711: 小奇挖矿 树形DP

    这个状态的定义非常难想吧...

    $f[x][y]$ 表示以 $x$ 为根的子树中,其余点全部移到了应该移动到的位置,也建设了应该建设的仓库,而 $x$ 移动到 $y$ 的最小代价.   

    这里是事前钦定 $y$ 不建立仓库的.     

    那么,我们考虑如何从 $x$ 的儿子转移到 $x$:   

    若 $f[son][b]$ 中 $b$ 与 $y$ 相等,则 $f[x][y]=f[x'][y]+f[son][y]$  
    若 $f[son][b]$ 中 $b$ 与 $y$ 不相等,且 $b$ 在 $son$ 的子树中,则直接让 $son$ 去 $b$ 就好了.  

    最后一种情况:$b$ 与 $y$ 不相等,且 $b$ 在 $son$ 的子树外,那么你发现这个一定没有 $b$ 与 $y$ 相等的优,按照第二种方式转移就行(反正不会起贡献)    

    code:

    #include <cstdio> 
    #include <string> 
    #include <cstring>   
    #define N 205       
    #define ll long long
    using namespace std;  
    void setIO(string s) 
    {
        freopen((s+".in").c_str(),"r",stdin);  
    } 
    int n,K,edges; 
    int val[N],dis[N][N],hd[N],to[N<<1],nex[N<<1],f[N][N];  
    void add(int u,int v) 
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; 
    }
    void dfs(int u,int ff) 
    {     
        for(int i=hd[u];i;i=nex[i]) if(to[i]!=ff) dfs(to[i],u);    
        for(int i=1;i<=n;++i) 
        {
            f[u][i]=dis[u][i];          
            for(int j=hd[u];j;j=nex[j]) 
            {
                int y=to[j]; 
                int tmp=f[y][i];     
                if(y==ff) continue;     
                for(int k=1;k<=n;++k) tmp=min(tmp,f[y][k]+K);        
                f[u][i]+=tmp;                 
            }   
        }
    }
    void getdis(int pr,int d,int u,int ff) 
    {     
        for(int i=hd[u];i;i=nex[i])   
            if(to[i]!=ff) dis[pr][to[i]]=val[d],getdis(pr,d+1,to[i],u);       
    }
    int main() 
    { 
        // setIO("input");  
        int i,j;     
        scanf("%d%d",&n,&K);  
        for(i=1;i<n;++i) scanf("%d",&val[i]);  
        for(i=1;i<n;++i) 
        {
            int x,y; 
            scanf("%d%d",&x,&y); 
            add(x,y),add(y,x); 
        }      
        for(i=1;i<=n;++i) getdis(i,1,i,0);             
        dfs(1,0); 
        int cur=1e9; 
        for(i=1;i<=n;++i) cur=min(cur,f[1][i]); 
        printf("%d
    ",cur+K);  
        return 0; 
    }
    

      

  • 相关阅读:
    数据库插入数据返回当前主键ID值方法
    兼容SQLSERVER、Oracle、MYSQL、SQLITE的超级DBHelper
    C# listview 单击列头实现排序 <二>
    C# ListView点击列头进行排序
    MessageBox.Show()的各种用法
    QT 删除文件指定目录
    hihoCoder 1015 KMP算法
    hiho一下 第五十周 (求欧拉路径)
    hdu
    hiho一下 第四十九周 欧拉路
  • 原文地址:https://www.cnblogs.com/guangheli/p/12128251.html
Copyright © 2011-2022 走看看