最大加权独立集问题

若加 权图 G=fV,目的顶点集  的子集  中的任何 顶点  之间都不相邻 ,则称  为 图 G的独立集 ,顶点个数最多的独  立集称为最大独立 集。各顶点权 重之和最大 的独立集称为图  G的最大加权独立集 。如图 1所示 ,顶点集合 (4,3,1)是该图  的一个独立集, 且是最 大独立集 ,但不是最大加权独立集 。  顶点集合(5,2)是独立集,且是最大加权独立集 。最大加权独  立集 问题 已被证明为是个 NP完全问题。

一棵树,每个点有一个权值,选择一个权值最大的无父子节点点集。

关键词:树的最大”权值“独立集

f[i][0]:以i为根的子树不选根节点最大权值,

f[i][1]:以i为根的子树选根节点最大权值

f[u][1]+=f[v][0];

f[u][0]+=max(f[v][1],f[v][0]);


注:

1.若所有点的权值都大于0,则树的最大”权值“独立集也是极大点独立集,即任选两个点,一定有且仅有一个在该集合中。若存在点的权值小于0,则不一定成立。

变题:选择一个无祖先与后代节点的最大权值点集

f[u]:以i为根的子树的最大权值

f[u]=max{ w[u],sum{f[v]},v是u的孩子 } 两个选择:当前节点/后代,两个选择互斥

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#define ll long long
#define sf scanf
#define pf printf
#define maxn 10000
#define inf 0x3f3f3f
#define INF 1ll<<60
#define mem(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x&(-x)
using namespace std;
 
 
int n;
int a[maxn],du[maxn];
 
struct Edge{
    int to,next;
}edge[maxn];
int head[maxn],tot;
int f[maxn][2];//f[u][0]:子树不含u的最大欢乐值 f[u][1]:子树含u的最大欢乐值
 
void add(int a,int b){
    edge[tot].to=b,edge[tot].next=head[a],head[a]=tot++;
}
 
void dp(int u){
    f[u][1]=a[u],f[u][0]=0;
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].to;
        dp(v);
        f[u][1]+=f[v][0];
        f[u][0]+=max(f[v][1],f[v][0]);
    }
}
 
int main(){
    //freopen("a.txt","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    mem(head,-1),mem(du,0),mem(f,0),tot=0;
    for(int i=1;i<n;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        add(b,a);
        du[a]++;
    }
    for(int i=1;i<=n;i++)
        if(!du[i]) {dp(i);printf("%d\n",max(f[i][0],f[i][1]));break;}
}


原文链接:https://blog.csdn.net/u013514182/article/details/42202021

加权树的最大权重独立集(Maximum Weight Independent Set, MWIS)问题是一个经典的组合优化问题。我们可以利用动态规划和递归公式来求解这个问题。下面是详细的解析过程: ### 1. 问题定义 给定一棵加权树,每个节点都有一个权重,要求找到一个独立的节点集合,使得这些节点的权重之和最大,并且集合中的任意两个节点都不相邻。 ### 2. 动态规划思路 我们使用动态规划来解决这个最大权重独立集问题。对于每一个节点,我们考虑两种情况: - 这个节点是否在独立集中。 - 这个节点不在独立集中。 ### 3. 递归公式 设 `dp[i]` 表示以节点 `i` 为根的子树的最大权重独立集的值。递归公式如下: \[ dp[i] = \max(w[i] + \sum_{j \in children(i)} dp[j], \sum_{j \in children(i)} (dp[j] + w[j])) \] 其中: - `w[i]` 是节点 `i` 的权重。 - `children(i)` 是节点 `i` 的所有子节点。 - `dp[j]` 是节点 `j` 为根的子树的最大权重独立集的值。 解释: - `w[i] + \sum_{j \in children(i)} dp[j]`:节点 `i` 在独立集中,那么它的所有子节点都不能在独立集中,所以取子节点的 `dp` 值。 - `\sum_{j \in children(i)} (dp[j] + w[j])`:节点 `i` 不在独立集中,那么它的所有子节点都可以在独立集中,所以加上子节点的 `dp` 值和权重。 ### 4. 具体步骤 1. 对树进行一次DFS遍历,计算每个节点的子树的 `dp` 值。 2. 返回根节点的 `dp` 值即为整个树的最大权重独立集的值。 ### 5. 示例代码 ```python def max_weight_independent_set(tree, weights): n = len(tree) dp = [0] * n def dfs(node): dp[node] = weights[node] for child in tree[node]: dfs(child) dp[node] = max(dp[node], dp[child] + weights[child]) dfs(0) # 从根节点开始DFS遍历 return dp[0] # 示例用法 tree = { 0: [1, 2], 1: [3], 2: [4], } weights = [10, 20, 30, 40, 50] print(max_weight_independent_set(tree, weights)) # 输出结果 ``` ### 6. 相关问题 1. 如果树不是二叉树,上述方法是否仍然适用? 2. 如何将这个方法扩展到一般图的最大权重独立集问题? 3. 是否有其他更高效的算法可以解决加权树的最大权重独立集问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值