POJ 1155 TELE(树形DP)

题意:

有一个电视台广播节目,广播的网络用一棵树表示,节点1表示电台,叶子结点表示用户,用户愿意付一定的钱去收看这个节目,

从非叶子结点到其他结点需要一定的费用(即从中继点到另一个中继点需要一些钱),问最后在不亏本的情况下,最多能使多少人收看到节目。

思路:

1. 和 POJ 1947 类似的题目,dp[u][i] 表示 u 节点为根,保留 i 个节点的最大盈利。

2. dp[u][i] = max(dp[u][i], dp[u][i-j] + dp[v][j] - w)

3. 如果叶子节点选定,则从叶子到根的一条路径上面的节点都应该被选定,所以初始化的时候赋值为 -INFS,只有当dp[叶子][i] 合法时,dp[rt][]才能合法。

4. sum[u] 表示以 u 为根节点的子树能覆盖多少个有效用户。算是解题中的一点优化。

 

#include <iostream>

#include <algorithm>

using namespace std;



const int MAXN = 3010;

const int INFS = 0x3fffffff;



structedge {

    int v, c;

    edge* next;

} *V[MAXN], ES[MAXN * 3];



int EC, N, M, sum[MAXN], dp[MAXN][MAXN];



void addedge(int u, int v, int c)

{

    ES[++EC].next = V[u];

    V[u] = ES + EC; 

    V[u]->v = v, V[u]->c = c;

}



void initdata()

{

    for (int i = 1; i <= N; ++i)

    {

        dp[i][0] = 0;

        for (int j = 1; j <= M; ++j)

            dp[i][j] = -INFS;

    }



    EC = 0;

    memset(V, 0, sizeof(V));



    for (int i = 1; i <= N - M; ++i)

    {

        int k, a, b;

        scanf("%d", &k);

        for (int j = 0; j < k; ++j)

        {

            scanf("%d %d", &a, &b);

            addedge(i, a, b);

            addedge(a, i, b);

        }

    }



    memset(sum, 0, sizeof(sum));

    for (int i = N - M + 1; i <= N; ++i)

        scanf("%d", &dp[i][1]), sum[i] = 1;

}



void treedp(int u, int f)

{

    for (edge* e = V[u]; e; e = e->next)

    {

        if (e->v == f)

            continue;



        treedp(e->v, u);

        sum[u] += sum[e->v];



        for (int i = sum[u]; i >= 1; --i)

            for (int j = 1; j <= i; ++j)

                if (dp[u][i-j] != -INFS && dp[e->v][j] != -INFS)

                    dp[u][i] = max(dp[u][i], dp[u][i-j] + dp[e->v][j] - e->c);

    }

}



int main()

{

    while (scanf("%d %d", &N, &M) != EOF)

    {

        initdata();

        treedp(1, 0);



        int i;

        for (i = M; i >= 0; --i)

            if (dp[1][i] >= 0)

                break ;



        printf("%d\n", i);

    }

    return 0;

}

你可能感兴趣的:(poj)