bzoj4987 Tree tree backpack

Topic Portal

https://lydsy.com/JudgeOnline/problem.php?id=4987

answer

A pretty good question slightly.

It is easy to find a conclusion: This \ (K \) must have a block of points constituted of communication, and take the time to traverse some means should be similar in accordance dfs continuous walking.

You can find the final answer should be: come out of a sub-tree root, such a situation to a subtree go, there may be from the root to a sub-tree situation to go; the same time, the process will be used from go to the root of the subtree again the case back to the roots. Three cases need to be considered.

Thus for DP tree, so \ (dp [x] [i ] [0/1/2] \) represented by \ (X \) subtree rooted, select the \ (I \) points, where to go from the root to the subtree again and again back to the root / tree from the root to a child to go (equivalent to a child from the tree to the root) / sub out from one tree to the root, to a subtree to three case, the transfer time, a second dimension backpack directly combined, the third dimension is such that: \ (0 + 0 \ to 0, + 0. 1 \ to. 1,. 1 + 0 \ to. 1, 0 + 2 \ to 2, 1 + 1 \ to 2, 2 + 0 \ to 2 \) .


Code below, the time complexity is generally combined backpack \ (O (NK) \) .

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back

template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}

typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;

template<typename I> inline void read(I &x) {
    int f = 0, c;
    while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    x = c & 15;
    while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    f ? x = -x : 0;
}

const int N = 3000 + 7;
const int INF = 0x3f3f3f3f;

int n, m, ans;
int dp[N][N][3], siz[N];

struct Edge { int to, ne, w; } g[N << 1]; int head[N], tot;
inline void addedge(int x, int y, int z) { g[++tot].to = y, g[tot].w = z, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y, int z) { addedge(x, y, z), addedge(y, x, z); }

inline void dfs(int x, int fa = 0) {
    dp[x][1][0] = dp[x][1][1] = 0;
    siz[x] = 1;
    for fec(i, x, y) if (y != fa) {
        dfs(y, x);
        int w = g[i].w;
        for (int i = std::min(m, siz[x]); i; --i)
            for (int j = 1; j <= std::min(m, siz[y]); ++j) {
                smin(dp[x][i + j][0], dp[x][i][0] + dp[y][j][0] + w * 2);
                smin(dp[x][i + j][1], dp[x][i][0] + dp[y][j][1] + w);
                smin(dp[x][i + j][1], dp[x][i][1] + dp[y][j][0] + w * 2);
                smin(dp[x][i + j][2], dp[x][i][0] + dp[y][j][2] + w * 2);
                smin(dp[x][i + j][2], dp[x][i][1] + dp[y][j][1] + w);
                smin(dp[x][i + j][2], dp[x][i][2] + dp[y][j][0] + w * 2);
            }
        siz[x] += siz[y];
    }
    smin(ans, dp[x][m][0]), smin(ans, dp[x][m][1]), smin(ans, dp[x][m][2]);
//  dbg("x = %d: ", x);
//  for (int i = 1; i <= m; ++i) dbg("%d:(%d, %d, %d) ", i, dp[x][i][0], dp[x][i][1], dp[x][i][2]);
//  dbg("\n");
}

inline void work() {
    memset(dp, 0x3f, sizeof(dp));
    ans = INF;
    dfs(1);
    printf("%d\n", ans);
}

inline void init() {
    read(n), read(m);
    int x, y, z;
    for (int i = 1; i < n; ++i) read(x), read(y), read(z), adde(x, y, z);
}

int main() {
#ifdef hzhkk
    freopen("hkk.in", "r", stdin);
#endif
    init();
    work();
    fclose(stdin), fclose(stdout);
    return 0;
}

Guess you like

Origin www.cnblogs.com/hankeke/p/bzoj4987.html