首页 > 代码库 > 树的最大独立集

树的最大独立集

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 ratingint d[maxn + 5][2];int visit[maxn + 5][2]; // d[u][k] already calculated// the supervisor relation forms a treeint parent[maxn + 5];int root;vector<int> sons[maxn + 5]; // sons of a parent// d[u][k], k==1 or k==0// depth first searchint 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;}

 

树的最大独立集