树的最大独立集

p280 9.4.2

原问题d(i)是以i为根节点,子问题是以i的儿子节点和以i的孙子节点为根节点。

讲解中的“当计算出一个d(i)后,用它去更新i的父亲和祖父节点的累加值”,对应到代码,需要从树的叶子节点开始计算d(i),可以用dfs

下面是 poj 2342的代码,例题9-13 UVa 1220 对应 poj 3342

#define _CRT_SECURE_NO_WARNINGS

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

int N;// 1 <= N <= 6000;
const int maxn = 6000;
// d[u][0]表示当不选前节点u,能获得的最大conviviality rating
// d[u][1]表示当选择前结点u,能获得的最大conviviality rating
int d[maxn + 5][2];
int visit[maxn + 5][2]; // d[u][k] already calculated

// the supervisor relation forms a tree
int parent[maxn + 5];
int root;

vector<int> sons[maxn + 5]; // sons of a parent

// d[u][k], k==1 or k==0
// depth first search
int dp(int u, int k)
{
    if (visit[u][k] > 0)
        return d[u][k];

    if (k == 0)
        d[u][0] = 0;

    for (int j = 0; j < sons[u].size(); j++) { // for each son of vertex u
        int v = sons[u][j];

        if (k == 1) { // select u, not select v
            d[u][1] += dp(v,0); // dfs
        }
        else { // not select u, select or not select v
            d[u][0] += max(dp(v, 1), dp(v, 0)); // dfs
        }
    }

    visit[u][k] = 1;
    return d[u][k];
}

int main()
{
    while (scanf("%d", &N) != EOF){

        memset(d, 0, sizeof(d));
        memset(visit, 0, sizeof(visit));
        memset(parent, 0, sizeof(parent));
        for (int i = 1; i <= N; i++)
            sons[i].clear();

        for (int i = 1; i <= N; i++)
            scanf("%d", &d[i][1]);

        for (int i = 1; i <= N; i++){
            int L, K;
            scanf("%d%d", &L, &K);
            if (L == 0 && K == 0) // end of input
                break;
            parent[L] = K;
            sons[K].push_back(L);
        }

        for (int i = 1; i <= N; i++){
            if (parent[i] == 0){
                root = i;
                break;
            }
        }

        printf("%d\n", max(dp(root, 0), dp(root, 1)));
    }

    return 0;
}
时间: 2024-11-10 09:47:52

树的最大独立集的相关文章

UVa 1220 Hali-Bula的晚会(树的最大独立集)

https://vjudge.net/problem/UVA-1220 题意: 公司里有n个人形成一个树状结构,即除了老板以外每个员工都有唯一的直属上司.要求选尽量多的人,但不能同时选择一个人和他的直属上司.输出最多能选多少人并判断是否唯一. 思路: 树的最大独立集问题.就是需要额外判定是否是唯一的. 因为输入的都是人名,所以首先就是用map容器来处理,上下属的关系就用vector容器来处理. d[u][1]表示以u为根的子树中,选u点能得到的最大人数,f[u][1]判断这种方案是否唯一. d[

POJ3342 Party at Hali-Bula(树的最大独立集-树形DP-刷表法)

题意: 给定一个树,选择若干点,使得选择的结点中任一结点不会和它的子结点同时选择,求能选结点最大数量.同时判断方案数是否为一. 思路:树的最大独立集,用树形dp,dfs一遍找每个结点的父亲,是为了从下向上刷每个结点儿子的最大独立集和and每个结点孙子的最大独立集和的表 判断方案数是否唯一同样在树形dp的同时递推判断即可 算法复杂度可以是线性 //248K 0MS C++ #include<cstdio> #include<iostream> #include<cstring&

POJ 3342 Party at Hali-Bula (树形dp 树的最大独立集 判多解 好题)

Party at Hali-Bula Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5660   Accepted: 2022 Description Dear Contestant, I'm going to have a party at my villa at Hali-Bula to celebrate my retirement from BCM. I wish I could invite all my co

POJ3398Perfect Service[树形DP 树的最大独立集变形]

Perfect Service Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 1518   Accepted: 733 Description A network is composed of N computers connected by N − 1 communication links such that any two computers can be communicated via a unique rou

bzoj1124[POI2008]枪战maf tarjan+树规+贪心/线性DP

这代码快写死我了.....死人最多随便推推结论.死人最少,每个环可以单独考虑,每个环上挂着的每棵树也可以分别考虑.tarjan找出所有环,对环上每个点,求出选它和不选它时以它为根的树的最大独立集(就是最多活下来的人数),然后环上每个点选或不选对应的是一个“价值”,这个价值是那个点挂着的树里最多存活人数.先全都不选环上的点,算出选和不选时最大独立集的差值,问题变成有一个环,环上有一堆数(那些差值),选出一些不相邻的数使得和最大,然后我按着bzoj2151种树写了个贪心....这个贪心的思路也很神,

acm常见算法及例题

转自:http://blog.csdn.net/hengjie2009/article/details/7540135 acm常见算法及例题 初期:一.基本算法:     (1)枚举. (poj1753,poj2965)     (2)贪心(poj1328,poj2109,poj2586)     (3)递归和分治法.     (4)递推.     (5)构造法.(poj3295)     (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法

ACM算法总结及刷题参考

参考:http://bbs.byr.cn/#!article/ACM_ICPC/11777 OJ上的一些水题(可用来练手和增加自信)(poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094) 初期: 一.基本算法: (1)枚举. (poj1753,poj2965)    (2)贪心(poj1328,poj2109,poj2586)    (3)递归和分治法.     (4)递推.     (5)构造法.(po

UVA - 1220 Party at Hali-Bula

题目大意:n 个人形成一个关系树,每个节点代表一个人,节点的根表示这个人的唯一的直接上司,只有根没有上司.要求选取一部分人出来,使得每 2 个人之间不能有直接的上下级的关系, 求最多能选多少个人出来,并且求出获得最大人数的选人方案是否唯一. 解题思路:分析发现是要求一个树的最大独立集.这里可以用树形 DP 解决. 定义dp[x][0]:表示在 i 点不选 i 点的以 x 为子树的最大独立集 而dp[x][1] 表示x到场的最大独立集 定义f [x][0]:表示以x为根且x点不选的子树是否唯一 ,

Party at Hali-Bula UVA - 1220 (树形dp)

Party at Hali-Bula UVA - 1220 题意:选一个公司的人去参加晚会,要求不能选有直接上下级关系的人,问最多选多少人去,并判断方案是否唯一. 树的最大独立集,并判断是否唯一. d[u][1]表示选u,d[u][0]表示不选u f[u][1]==1表示选u的情况下唯一,f[u][1]==0表示不唯一 f[u][0]为不选u的情况下的唯一性 1 #include <cstdio> 2 #include <bits/stdc++.h> 3 using namespa