Fzu 2157 ProgramCaicai's Trees【树型dp】

本文介绍了一道关于树形结构的动态规划问题,通过设定dp[i][2]表示节点i被标记为0或1的最小花费,从根节点开始进行深度优先搜索并更新dp值,最终得出整棵树的最小成本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 Problem 2157 ProgramCaicai's Trees

Accept: 62    Submit: 155
Time Limit: 15000 mSec    Memory Limit : 32768 KB

 Problem Description

Given a Tree of N nodes.

Each node has exactly two labels.(0 and 1).

You must choose which label to assign to give the minimum cost.

The Cost is the sum of two parts:

1. For each node their is a cost assigned to the node for a given label.

2. For each pairs of Node connected their is a cost assigned to it according to it's labels.

 Input

In the first line, there are a number T(<=50) denotes the number of test cases.

In the second line, there are a number N(<=200000) denoting the number of Nodes.

In the third line, N numbers denoting the cost for each node assigned to label 0.

In the fourth line, N numbers denoting the cost for each node assigned to label 1.

In the next n-1 lines. each line containing six numbers P Q A B C D, P Q indicates there is a edge between P and Q , and A B C D are cost assigned to pairs of nodes which label is 00 01 10 11 accordingly.

The Tree root is always Node 1

Every cost is between 0 and 100

only 2 big cases

 Output

The Minimum cost of the given tree.(A Integer)

 Sample Input

1
4
3 1 1 3
4 0 0 4
1 2 0 1 1 0
2 3 0 1 1 0
2 4 0 1 1 0

 Sample Output

8

题目大意:


一共有N个点,每个点只能标号为0或者1 ,已知一个点被标号0或者1的价值,以及两个点之间两点设定的标号的边的权值,问设定完,整个图所有权值加和最小是多少。


思路:


一道树Dp.


设定dp【i】【2】表示节点i标号为0或者1的最小花费。

那么我们从节点1开始Dfs并且维护Dp值即可。

不难推出其状态转移方程:

dp【i】【0】+=min(dp【v】【0】+a【0】【0】+dp【v】【1】+a【0】【1】);

dp【i】【1】+=min(dp【v】【0】+a【1】【0】+dp【v】【1】+a【1】【1】);


Ac代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
struct node
{
    int from;
    int to;
    int w1;
    int w2;
    int w3;
    int w4;
    int next;
}e[200050*2];
int head[200050];
int a[200050];
int b[200050];
int dp[200050][2];
int cont;
void add(int from,int to,int a,int b,int c,int d)
{
    e[cont].to=to;
    e[cont].w1=a;
    e[cont].w2=b;
    e[cont].w3=c;
    e[cont].w4=d;
    e[cont].next=head[from];
    head[from]=cont++;
}
int Dp(int u,int from)
{
    dp[u][0]=a[u];
    dp[u][1]=b[u];
    for(int i=head[u];i!=-1;i=e[i].next)
    {
        int v=e[i].to;
        int w1=e[i].w1;
        int w2=e[i].w2;
        int w3=e[i].w3;
        int w4=e[i].w4;
        if(v==from)continue;
        Dp(v,u);
        dp[u][0]+=min(dp[v][0]+w1,dp[v][1]+w2);
        dp[u][1]+=min(dp[v][0]+w3,dp[v][1]+w4);
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        cont=0;
        memset(dp,0,sizeof(dp));
        memset(head,-1,sizeof(head));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)scanf("%d",&b[i]);
        for(int i=1;i<=n-1;i++)
        {
            int x,y,w1,w2,w3,w4;
            scanf("%d%d%d%d%d%d",&x,&y,&w1,&w2,&w3,&w4);
            add(x,y,w1,w2,w3,w4);
            add(y,x,w1,w3,w2,w4);
        }
        Dp(1,-1);
       // printf("%d %d\n",dp[1][0],dp[1][1]);
        printf("%d\n",min(dp[1][1],dp[1][0]));
    }
}










dp【i】【0】+=min(dp【v】【0】+a【0】【0】+dp【v】【1】+a【0】【1】);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值