有向树k中值问题模板!!!(树行dp)

#include <iostream>
using namespace std ;

typedef struct binode
{
    int wx , w , wd , *cost , d ;//wi,vi,di分别表示编号为i 的顶点的权为wi,相应的有向边为(i, vi),其边长为di
    struct binode *parent , *left , *right ;
}binode , *link ;

int n , k ;
link *subt ;

link Newnode ()
{
    link p = new binode ;//p是节点型的指针
    p->d = p->w = p->wd = p->wx = 0 ;
    p->parent = p->left = p->right = NULL ;
    return p ;
}

void Addw (link t)
{
    t->wd = t->d * t->wx ;
    if (t->left)
    {
        t->w += t->left->w + t->right->w ;
        t->wd += t->left->wd + t->right->wd ;
    }
}

void Addd (link t)
{
    if (t->parent)
        t->d += t->parent->d ;
    t->cost = new int[k + 1] ;
}

void PostOrder (void(*Visit)(link u) , link t)
{
    if (t)
    {
        PostOrder (Visit , t->left) ;
        PostOrder (Visit , t->right) ;
        Visit (t) ;
    }
}

void PreOrder (void(*Visit)(link u) , link t)//前一个参数是一个函数的的指针
{
    if (t)
    {
        Visit (t) ;
        PreOrder (Visit , t->left) ;
        PreOrder (Visit , t->right) ;
    }
}

link Findc (link q)
{
    while (q->right)
        q = q->right ;
    return q ;
}

void Init ()
{
    int i , a , b , c ;
    link p , q ;
    cin >> n >> k ;//n个节点,k个中转站
    subt = new link [n + 1] ;//subt是指针的指针
    for (i = 0 ; i <= n ; i ++)
        subt[i] = Newnode () ;//subt[i]是指向第i个节点的指针
    for (i = 1 ; i <= n ; i ++)
    {
        cin >> a >> b >> c ;
        subt[i]->wx = subt[i]->w = a ;//a表示该顶点的权
        subt[i]->d = c ;//c表示(i,b)的距离
        p = Findc (subt[b]) ;//找到b节点的最右子节点
        q = Newnode () ;
        p->left = subt[i] ;
        p->right = q ;//为p所指向的节点添加叶子节点使所有的点的右子树为空
        subt[i]->parent = q->parent = p ;
    }
    PreOrder (Addd , subt[0]) ;//?????????????????????
    PostOrder (Addw , subt[0]) ;//????????????????????
}

void Comp (link t)
{
    int i , j , tmp ;
    if (!t->left)
    {
        t->cost[0] = t->d * t->wx ;//这行的意思是设置t点为服务机构,可当i == 0 ,此时总的可设的服务机构都等于0,怎么能在t点处设服务机构呢!
        for (i = 1 ; i <= k ; i ++)
            t->cost[i] = 0 ;
    }
    else
    {
        for (i = 0 ; i <= k ; i ++)
        {
            /*if (i)*/
                t->cost[i] = t->wd - t->w * t->d ;
            /*else
                t->cost[i] = INT_MAX ;*/
            for (j = 0 ; j <= i ; j ++)
            {
                tmp = t->left->cost[j] + t->right->cost[i - j] + t->wx * t->d ;
                if (tmp < t->cost[i])
                    t->cost[i] = tmp ;
            }
        }
    }
}

int Solution ()
{
    PostOrder (Comp , subt[0]) ;
    return subt[0]->cost[k] ;
}

int main ()
{
    Init () ;
    cout << Solution () ;
    return 0 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值