Tree of tree

题意:
一棵结点带权树,大小(结点数)为k的子树的权值和最大为多少。

初步分析
这道题其实就是一道01背包问题只是是在树上做而已。背包的总容量就是k个结点(一定得刚好装满),每个物品的价值就是结点的权值w[i].注意,并不是随便选取结点就行了。而是一定得是子树。那么这一点我们要怎么实现呢。首先我们用dp[i][j]来表示以结点i为首的结点数为j的权值最大的一棵子树。那么dp[i][j]的状态方程怎么写呢?dp[i][j]=max(dp[i][j],dp[i][j-w]+dp[v][w])(v是结点i的子节点,1=<j<=cnt[i],0<w<j)注意我们是怎么保证dp[i][j]表示的是以结点i为首的子树呢?新节点所能取得的最大结点数只能是j-1,因为dp[i][1]始终代表的是结点i,所以才能保证都是以结点i为首的子树。而且由于是01背包所以我们的背包容量j从大到小更新,这样保证所有的小值都是上一次子节点的更新值而不是重复使用当前结点的值(不然的话就变成完全背包了)。

直接上代码

#include <iostream>
#include <string.h>
using  namespace std;
const int MAX_N=110;
const int MAX_M=220;
int w[MAX_N];
int dp[MAX_N][MAX_N];
int cnt[MAX_N];
int n,k,answer=0;

//我们这里用图来储存树,在遍历的时候通过一个father参数就可以转化为树了。没有必要用一个father数组来储存
int ans=0;
int head[MAX_N];
struct edge{
    int v;
    int next;
}eid[MAX_M];

void insert(int u,int v){
    eid[ans].v=v;
    eid[ans].next=head[u];
    head[u]=ans++;
}

int read(){
    int w=1,s=0;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-'){
           w*=-1;
        }
        ch=getchar();
    }
    while(isdigit(ch)){
        s=(s<<1)+(s<<3)+ch-48;
        ch=getchar();
    }
    return s*w;
}
int dfs(int node,int father){
    cnt[node]=1;
    for(int i=head[node];i!=-1;i=eid[i].next){
        int v=eid[i].v;
        if(v==father) continue;
        cnt[node]+=dfs(v,node);
    }
    dp[node][1]=w[node];

    for(int i=head[node];i!=-1;i=eid[i].next){
        int v=eid[i].v;
        if(v==father) continue;
        for(int j=cnt[node];j>=1;--j) {
            for (int m = 0; m <=cnt[v] && m<j ; ++m) {
                dp[node][j] = max(dp[node][j], dp[node][j - m]+dp[v][m]);
            }
        }
    }

    answer=max(answer,dp[node][k]);

    return cnt[node];
}

int main() {

    while(scanf("%d %d",&n,&k)!=EOF) {

        for (int i = 1; i <= n; ++i) {
            w[i] = read();
        }
        memset(head, -1, sizeof(head));
        ans=0;
        for (int i = 0; i <MAX_N; ++i) {
            for (int j = 0; j <MAX_N; ++j) {
                dp[i][j] = 0;
            }
        }

        for (int i = 1; i <= n - 1; ++i) {
            int x, y;
            x = read()+1;
            y = read()+1;

            insert(x, y);
            insert(y, x);
        }

        dfs(1, -1);
        cout <<answer<<endl;
        answer=0;
    }
    return 0;
}
### Tree of Thoughts概念解析 #### 定义与概述 Tree of Thoughts是一种用于表示复杂决策过程的数据结构,其中每个节点代表一个思考状态或假设。该树形结构允许算法通过分支来探索不同的解决方案路径,直到找到最优解为止[^1]。 #### 结构特点 - **根节点**:通常初始化为起始条件或问题描述。 - **内部节点**:这些节点包含了基于前驱节点做出的不同选择的结果;每一个新决定都会创建一个新的子节点。 - **叶节点**:当达到某个终止标准时形成叶子结点,这可能意味着找到了可行方案或是穷尽了当前路径上的选项。 #### 应用场景 在计算机科学领域内,Tree of Thoughts被广泛应用于解决需要多步推理的问题上,比如游戏AI设计、自动规划以及自然语言处理中的对话管理等任务中。它有助于系统化地评估各种可能性并从中挑选最佳行动路线。 ```python class ThoughtNode: def __init__(self, state=None): self.state = state # 当前思考的状态 self.children = [] # 子节点列表 def add_child(self, child_node): """ 添加子节点 """ self.children.append(child_node) def expand_thought_tree(root, generate_next_states_func): """ 扩展思维树 """ frontier = [root] while frontier: current_node = frontier.pop(0) next_states = generate_next_states_func(current_node.state) for new_state in next_states: child_node = ThoughtNode(new_state) current_node.add_child(child_node) frontier.append(child_node) ``` 此代码片段展示了如何构建和扩展一棵简单的Thoughts树。`generate_next_states_func`函数负责根据给定状态生成后续可能的状态集合,从而实现对整个搜索空间的有效遍历。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值