BZOJ 4711: 小奇挖矿 树形DP

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

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\n",cur+K);  
    return 0; 
}

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/12128251.html