[2019-11-10] thinking training school

[Title] summarized

In a \ (n-\) points of the tree, to find a length \ (K \) chain (covering \ (k + 1 \) point), so that the minimum distance between all points of this chain.

[Thinking] Points

  • First define \ (siz [u] \) represented by \ (U \) is the root of the subtree size, \ (G [U] \) represents \ (U \) all points to the sub-tree \ (U \) and distance, \ (H [U] \) represents \ (U \) external to the subtree nodes \ (U \) the sum of the distances.
  • \ (siz \) is better solved, \ (G [U] \) is actually \ (\ sum_ {v \ in Son [U]} SIZ [v] + G [v] \) , its meaning is one of each a point to \ (v \) on points plus \ (u-> v \) in \ (1 \) contributions, \ (H [U] \) to solve similar to \ (G \) , we consider from the father node \ (h [fa] \) to transfer.
  • The formula is \ (H [U] = H [FA] + G [FA] -g [U] -siz [U] +-n-SIZ [U] \) , the specific derivation process is divided into two parts, the first the point in the non-child tree \ (FA \) plus the distance calculated after the \ (fa-> u \) distance.
  • Next, consider the tree \ (DP \) .
  • We define \ (dp [u] [i ] \) represents a section of chain in \ (U \) , and this chain cover \ (I \) points, other points in this subtree to minimize this chain distance.
  • State transition equation: \ (DP [U] [I] = min (DP [U] [I], DP [V] [I-. 1] + G [U] -g [V] -siz [V]) \ ) is the point to the remaining sub-tree \ (U \) a constant ratio to the distance \ (V \) distinctions.
  • Then the overall answer is \ (min (dp [u] [k + 1]) \) that is part of the answer.
  • There is part of the answer, two merge subtrees get answers.
  • I.e. \ (min (dp [u] [i], dp [v] [k + 1-i]) \)
  • Time complexity \ (\ mathcal O (nk) \)

[Code]

#include <bits/stdc++.h>

#define int long long 

#define FI first
#define SE second
#define REP(i, s, t) for (int i = s; i <= t; i++)
#define PER(i, s, t) for (int i = s; i >= t; i--)
#define pb push_back
#define mp make_pair
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f

using namespace std;

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

template <class T> void chkmax(T& x, T y) { x = max(x, y); }
template <class T> void chkmin(T& x, T y) { x = min(x, y); }

char gc() {
  static char buf[1 << 25], *p1 = buf, *p2 = buf; 
  return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 25, stdin), p1 == p2) ? EOF : *p1++;
}

template <class T>
void re(T& x) {
  x = 0; char ch = 0; int f = 1;
  for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
  x *= f;
}

template <class T>
void pr(T x) {
  if (!x) { putchar('0'); return; }
  if (x < 0) x = -x, putchar('-');
  static int stk[25], top; top = 0; 
  while (x) { stk[++top] = x % 10; x /= 10; }
  while (top) putchar(stk[top--] + 48); 
}

const int N = 1e4 + 5;

vector<int> G[N];

int n, k, ans;
int siz[N], g[N], h[N];
int dp[N][105];

void dfs1(int u, int fff) {
  siz[u] = 1, g[u] = 0;
  for (auto v : G[u]) {
    if (v == fff)
      continue;
    dfs1(v, u);
    siz[u] += siz[v];
    g[u] += siz[v] + g[v];
  }
}

void dfs2(int u, int fff) {
  dp[u][1] = g[u];
  if (fff)
    h[u] = h[fff] + g[fff] - g[u] - siz[u] + n - siz[u];
  for (auto v : G[u]) {
    if (v == fff)
      continue;
    dfs2(v, u);
    for (int i = 0; i <= k + 1; i++) 
      chkmin(ans, dp[u][k + 1 - i] + dp[v][i] + h[u] - g[v] - siz[v]);
    for (int i = 1; i <= k + 1; i++)
      chkmin(dp[u][i], dp[v][i - 1] + g[u] - g[v] - siz[v]);
  }
  chkmin(ans, dp[u][k + 1] + h[u]);
}

void init() {
  ans = inf;
  for (int i = 1; i <= n; i++)
    G[i].clear(), siz[i] = 0, g[i] = 0, h[i] = 0;
  memset(dp, 0x3f, sizeof dp);
}

signed main() {
  while (1) {
    re(n), re(k);
    if (n == 0 && k == 0)
      return 0;
    init();
    for (int i = 1; i < n; i++) {
      int u, v; re(u), re(v);
      u++, v++;
      G[u].pb(v); 
      G[v].pb(u);
    }
    dfs1(1, 0);
    dfs2(1, 0);
    pr(ans), puts("");
  }
  return 0; 
}

Guess you like

Origin www.cnblogs.com/chhokmah/p/11838471.html