Блог пользователя _Jain_

Автор _Jain_, история, 10 месяцев назад, По-английски

You are given a tree with nodes, numbered from 1 to n. Each node has an integer value .

You can perform at most k operations. In one operation, you may pick a leaf node and reattach it to any node.

After all operations, define Xi as the sum of values in the subtree rooted at node i . Your goal is to minimize sum of All Xi.

  • Проголосовать: нравится
  • +13
  • Проголосовать: не нравится

»
10 месяцев назад, скрыть # |
 
Проголосовать: нравится +3 Проголосовать: не нравится

did this question come in any OA?

»
10 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

I was thinking of solving it using DP.For each node, I keep a dp[u][k], which means the maximum gain we can get from the subtree of u if we do exactly k operations inside it. It's like a knapsack: each child subtree gives us some set of gains based on how many moves we spend on it,and we want to combine them to get the best possible total using at most K moves. O(n*k*(work on each state))= o(n*k*(nk*k))

Gain : let's say u have a leaf at depth d when u reattach it to root overall score will decrease by (d-1)*node_val We can precompute this using dfs in o(n)

If some one has better approsch PLZZ SHARE

  • »
    »
    10 месяцев назад, скрыть # ^ |
     
    Проголосовать: нравится +6 Проголосовать: не нравится

    As far as I know, that is the most optimal solution, since the problem is equivalent to knapsack problem. TC should be O(n*k*k) if we do transitions directly.

    • »
      »
      »
      10 месяцев назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится

      Oo!!..can u share the transitions..or do u I think I am evaluating time complexity of my code incorrectly?

      • »
        »
        »
        »
        10 месяцев назад, скрыть # ^ |
         
        Проголосовать: нравится +10 Проголосовать: не нравится

        dp[v][i] = max(dp[v][i],dp[v][j]+dp[u][k]) where j+k = i, v is a parent of u. Base is dp[v][sz(v)] = benefit if we delete the whole subtree, other values are 0.

        • »
          »
          »
          »
          »
          10 месяцев назад, скрыть # ^ |
          Rev. 2  
          Проголосовать: нравится 0 Проголосовать: не нравится

          Why u are considering it a binary tree?

          is this what you want to say?

          Code
          • »
            »
            »
            »
            »
            »
            9 месяцев назад, скрыть # ^ |
             
            Проголосовать: нравится 0 Проголосовать: не нравится

            I am updating dp[v] by iterating over its children one by one.

            Code
            • »
              »
              »
              »
              »
              »
              »
              9 месяцев назад, скрыть # ^ |
               
              Проголосовать: нравится 0 Проголосовать: не нравится

              Basically you are distributing each i from 0,k

              between node and the child. But this is not working

              • »
                »
                »
                »
                »
                »
                »
                »
                9 месяцев назад, скрыть # ^ |
                 
                Проголосовать: нравится 0 Проголосовать: не нравится

                It should be working. Here is my full solution:

                Code
  • »
    »
    10 месяцев назад, скрыть # ^ |
    Rev. 3  
    Проголосовать: нравится 0 Проголосовать: не нравится

    do you remember the constraints of the problem?? Thought about it for 10-15 mins, first fell trap to greedy. I have also come to a solution resembling yours! Knapsack DP on subtree sums

    Did you solve it during the Online Asssessment?

»
10 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

try to minimize the contribution of each node to the final answer

and contribution will be depth*a[i] or (depth+1)*a[i] according to your depth definiton

so remove the leaf with max value of depth*a[i] and put it to node ..

repeat the operation k times..

  • »
    »
    10 месяцев назад, скрыть # ^ |
     
    Проголосовать: нравится +6 Проголосовать: не нравится

    It wouldn't work since the set of leaves may change. For example, in the optimal answer we may use operation on a vertex and on its parent after that.

    • »
      »
      »
      10 месяцев назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится

      ohh yes greedy will be wrong.. then i think dp solution is good..

    • »
      »
      »
      10 месяцев назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится

      Depth matters because a node’s value contributes to the subtree sums of all its ancestors so more the depth more it adds to the total.That’s why just looking at a node’s value isn’t enough; we must also consider its depth. Greedy fails because sometimes a high-gain move is only possible after clearing its children first.So even if a leaf seems a bad choice now, moving it night unlock a much better move later.thats's why I dp can solve this.

»
10 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Are the values at the nodes all positive ? And what about the constraints ?

»
10 месяцев назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

Quite Nice Problem ! Here is my solution O(N*K) EULER TOUR + KNAPSACK

It is obvious that the contribution of a particular node is (depth[i] + 1) * val[i] (Considering depth of root to be 0)

Now some observations : ->For every node if at all we choose to apply operation then most optimal will be to connect that node directly to the root [Since that way contribution becomes 2 * val[i] and that's the min possible] ->If we apply the operation on a node then have to apply on every node in its subtree

So compute the gain (depth[i] — 1) * val[i] for all nodes And then sum all the gains from a subtree on the subtree's root also compute the subtree sizes

Let that array formed be arr Now perform EULER TOUR on the tree and let that array be 'e' (All subtree nodes follow their root node) now make the array a where a[i] = arr[e[i]]

Now apply knapsack on a and dp[i][k] = max(dp[i+1][k], a[i] + dp[i+ss[i]][k-ss[i]) ss[i] = subtree size of 'i'

»
10 месяцев назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

Do you remember the other problems ?

»
10 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

This solution would work I think. Used priority queue and then selected the top k contributors leaving beside the root and connected them to the root so that their contribution minimizes. contribution is just depth[node]*value[node]

void solve() {
  int n, k;
  cin >> n >> k;
  vector<int> a(n + 1);
  for (int i = 1; i <= n; i++) cin >> a[i];
  vector<vector<int>> g(n + 1);
  vector<int> deg(n + 1);
  for (int i = 0; i < n - 1; i++) {
    int u, v;
    cin >> u >> v;
    g[u].push_back(v);
    g[v].push_back(u);
    deg[u]++;
    deg[v]++;
  }

  vector<int> depth(n + 1), par(n + 1);
  queue<int> q;
  q.push(1);
  depth[1] = 1;
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int v : g[u]) {
      if (depth[v] == 0) {
        depth[v] = depth[u] + 1;
        par[v] = u;
        q.push(v);
      }
    }
  }

  long long ans = 0;
  for (int i = 1; i <= n; i++) ans += 1LL * a[i] * depth[i];

  priority_queue<pair<long long, int>> pq;
  for (int i = 2; i <= n; i++) {
    if (deg[i] == 1) {
      long long b = 1LL * a[i] * (depth[i] - 2);
      if (b > 0) pq.push({b, i});
    }
  }

  while (k-- and !pq.empty()) {
    auto [b, u] = pq.top();
    pq.pop();
    if (b <= 0) break;
    ans -= b;
    int p = par[u];
    deg[p]--;
    if (p != 1 and deg[p] == 1) {
      long long b2 = 1LL * a[p] * (depth[p] - 2);
      if (b2 > 0) pq.push({b2, p});
    }
  }

  cout << ans;
}
»
10 месяцев назад, скрыть # |
 
Проголосовать: нравится +3 Проголосовать: не нравится

I think this works fine. If some mistake is there please rectify.

Code
  • »
    »
    9 месяцев назад, скрыть # ^ |
    Rev. 2  
    Проголосовать: нравится 0 Проголосовать: не нравится

    1) You are outputting dp[1][k], instead of the answer.

    2) While iterating over 0 <= i <= k should go in descending order to avoid taking one subtree several times.

    3) dp[v][sz[v]] is miscalculated for v with at least 2 children.