最大加权独立集问题

Posted 软件工程小施同学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大加权独立集问题相关的知识,希望对你有一定的参考价值。

若加 权图 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

以上是关于最大加权独立集问题的主要内容,如果未能解决你的问题,请参考以下文章

最大独立集算法

[1143] [CTSC2008]祭祀river(最大独立集 || 偏序集最大反链)

树的最大独立集

树上的最大独立集

HDU 1565 1569 方格取数(最大点权独立集)

BZOJ 1143: [CTSC2008]祭祀river 最大独立集