bzoj 1812 river

来源:互联网 发布:淘宝玻璃茶具销量前十 编辑:程序博客网 时间:2024/06/07 18:31

树形dp,转化为儿子兄弟表示法成为一棵二叉树,然后用二叉树的角度dp

#include<bits/stdc++.h>#define rep(i,k,n) for(int i=k;i<=n;i++)using namespace std;const int maxn=20000;const int N=150;typedef long long ll;int head[N],tot=0;struct E{int to,next,w;E(int to=0,int next=0,int w=0):to(to),next(next),w(w){}}edge[maxn];void add(int x,int y,int w){    edge[++tot]=E(y,head[x],w);head[x]=tot;}int v[N],dis[N],n,K,ch[N][2];ll d[N][N][N];void dfs(int x){    for(int i=head[x];i;i=edge[i].next){        int v=edge[i].to;            dis[v]=edge[i].w+dis[x];            dfs(v);        }}void dfs2(int x){int last=0;        for(int i=head[x];i;i=edge[i].next){        int v=edge[i].to;        if(!ch[x][0])ch[x][0]=v;        if(last)ch[last][1]=v;        last=v;            dfs2(v);        }}ll dp(int x,int y,int k){if(!x)return 0;    if(d[x][y][k]!=d[n+2][n+2][n+2])return d[x][y][k];    //if(!ch[x][0]){if(k==1)return d[x][y][k]=0;return d[x][y][k]=1ll*(dis[x]-dis[y])*v[x];}    d[x][y][k]=0x7f7ff7f7f7f7f;    rep(i,0,k){ll tmp=(dis[x]-dis[y])*v[x];    if(ch[x][0])tmp+=dp(ch[x][0],y,i);    if(ch[x][1])tmp+=dp(ch[x][1],y,k-i);    d[x][y][k]=min(d[x][y][k],tmp);    if(i<k){        tmp=0;         if(ch[x][0])tmp+=dp(ch[x][0],x,i);         if(ch[x][1])tmp+=dp(ch[x][1],y,k-i-1);         d[x][y][k]=min(d[x][y][k],tmp);    }    }    return d[x][y][k];}int main(){//freopen("in.in","r",stdin);    scanf("%d%d",&n,&K);    int x,w;    rep(i,1,n){        scanf("%d%d%d",&v[i+1],&x,&w);x++;        add(x,i+1,w);    }dfs(1);    dfs2(1);    memset(d,-1,sizeof(d));    printf("%lld\n",dp(1,1,K));    return 0;}
0 0
原创粉丝点击