树上背包小结

P2014 [CTSC1997]选课

没有变形的树上背包

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <iostream>
#include <iomanip>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define LL long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f
#define PI 3.1415926535898
#define F first
#define S second
#define endl '\n'
#define lson  rt << 1
#define rson  rt << 1 | 1
#define f(x, y, z) for (int x = (y), __ = (z); x < __; ++x)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
using namespace std;
const int maxn = 307;
const int mod = 1e9 + 7;

int n, m;
int dp[maxn][maxn];
vector<int> G[maxn];

void work(int u)
{
	f(i, 0, G[u].size())
	{
		int v = G[u][i];
		work(v);
		for (int j = m + 1; j >= 1; j--)
		{
			for (int k = 0; k < j; k++) dp[u][j] = max(dp[u][j], dp[v][k] + dp[u][j - k]);
		}
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n >> m;
	int fa;
	_rep(i, 1, n)
	{
		cin >> fa >> dp[i][1];
		G[fa].push_back(i);
	}
	work(0);
	cout << dp[0][m + 1] << endl;
}

P1273 有线电视网

\(dp[u][v]\) 表示以u为根选取v个节点的最大收益,收益为正时表示可行

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <iostream>
#include <iomanip>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define LL long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f
#define PI 3.1415926535898
#define F first
#define S second
#define endl '\n'
#define lson  rt << 1
#define rson  rt << 1 | 1
#define f(x, y, z) for (int x = (y), __ = (z); x < __; ++x)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
using namespace std;
const int maxn = 3e3 + 7;
const int mod = 1e9 + 7;

int n, m;
int w[maxn];
int dp[maxn][maxn];
vector<pair <int, int> > G[maxn];

int dfs(int u)
{
    if (u > n - m)
    {
        dp[u][1] = w[u];
        return 1;
    }
    int leaf = 0;
    f(i, 0, G[u].size())
    {
        int v = G[u][i].F;
        int cst = G[u][i].S;
        int tmp = dfs(v);
        leaf += tmp;
        for(int j = leaf; j > 0; j--)
        {
            _rep(k, 0, tmp)
            {
                if (j - k < 0) break;
                dp[u][j] = max(dp[u][j], dp[u][j - k] + dp[v][k] - cst);
            }
        }
    }
    return leaf;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m;
    int cnt, x, y;
    memset(dp, -inf, sizeof(dp));
    _rep(i, 1, n) dp[i][0] = 0;
    _rep(i, 1, n - m)
    {
        cin >> cnt;
        _rep(j, 1, cnt)
        {
            cin >> x >> y;
            G[i].push_back({ x, y });
        }
    }
    _rep(i, n - m + 1, n)
    {
        cin >> w[i];
    }
    dfs(1);
    for (int i = m; i >= 0; i--)
    {
        if (dp[1][i] >= 0)
        {
            cout << i << endl;
            break;
        }
    }
}


POJ2486

\(dp[u][j][1]\) 表示从u开始走l步不回到u的最大收益,对某个子节点v考虑两种情况,经过u的其它子节点最后到v的任意子节点;经过v的子树后回到u,再到其它子节点。

\(dp[u][j][0]\) 表示从u开始走l步回到u的最大收益,从同状态的子节点转移。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <iostream>
#include <iomanip>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define LL long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f
#define PI 3.1415926535898
#define F first
#define S second
#define endl '\n'
#define lson  rt << 1
#define rson  rt << 1 | 1
#define f(x, y, z) for (int x = (y), __ = (z); x < __; ++x)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
using namespace std;
const int maxn = 107;
const int maxm = 207;
const int mod = 1e9 + 7;

int n, k;
int w[maxn];
int dp[maxn][maxm][2];
vector<int> G[maxn];

int dfs(int u, int f)
{
    dp[u][0][1] = dp[u][0][0] = w[u];
    for (int i = 0; i < G[u].size(); i++)
    {
        int v = G[u][i];
        if (v == f) continue;
        dfs(v, u);
        for (int j = k; j >= 1; j--)
        {
            for (int l = 0; l <= j - 1; l++)
            {
                dp[u][j][1] = max(dp[u][j][1], dp[u][j - l - 1][0] + dp[v][l][1]);
                if (l <= j - 2)
                {
                    dp[u][j][1] = max(dp[u][j][1], dp[u][j - l - 2][1] + dp[v][l][0]);
                    dp[u][j][0] = max(dp[u][j][0], dp[u][j - l - 2][0] + dp[v][l][0]);
                }
            }
        }
    }
    return 0;
}

int main()
{
    while (cin >> n >> k)
    {
        int x, y;
        memset(dp, 0, sizeof(dp));
        for (int i = 1; i <= n; i++)
        {
            cin >> x;
            w[i] = x;
            G[i].clear();
        }
        for (int i = 1; i <= n - 1; i++)
        {
            cin >> x >> y;
            G[x].push_back(y);
            G[y].push_back(x);
        }
        dfs(1, -1);
        int ans = 0;
        for (int i = 0; i <= k; i++) ans = max(ans, max(dp[1][i][1], dp[1][i][0]));
        cout << ans << endl;
    }

待补充

posted @ 2020-09-11 23:39  kurum!  阅读(119)  评论(0编辑  收藏  举报