Need help with recurrence for dp on tree problem.

Revision en2, by acash, 2022-11-22 19:19:56

Description

The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The cows didn't have time to rebuild any extra roads, so now there is exactly one way to get from any given barn to any other barn. Thus, the farm transportation system can be represented as a tree.

Farmer John wants to know how much damage another earthquake could do. He wants to know the minimum number of roads whose destruction would isolate a subtree of exactly P (1 <= P <= N) barns from the rest of the barns.

Problem link — http://poj.org/problem?id=1947

I am trying to understand the recurrence from below accepted solution but not able to understand few things. As per my understanding dp[i][j] = number of edges needs to be deleted for tree rooted at i having j nodes in that tree.

Doubt Is it included root or only considers child

dp [ cur ][ j ] = min ( dp [ cur ][ j ] , dp [ v ] [ k ] + dp [ cur ][ j — k ] — 2 ); } dp[cur][j] when not considering child v dp [ v ] [ k ] + dp [ cur ][ j — k ] — 2 ) when considering child v and taking k nodes from it and j — k from the previous child nodes.

Doubt why we are subtracting 2 when we include this child v rooted at v.

Accepted solution found from one blog(which does not have explanation to recurrence).

#include<stdio.h>
    #include<vector>
    #include<iostream>
    #define ll long long 
    #define pb push_back 
    #define pm make_pair 
    using  namespace  std ; 
    const  int  MAX  =  555 ; 
    const  int  INF  =  0x3f3f3f3f ; 
    int  dp [ MAX ][ MAX ] ; 
    // The minimum knife number 
    int  n  ,p;
    vector < int >  vv [ MAX ]; 
    void  dfs ( int  cur , int  rt ) { 
    int  up  =  vv [ cur ]. size (); 
    for ( int  i  =  0 ; i < up ; i ++ ) { 
        int  v  =  vv [ cur ][ i ]; 
        if ( v  ==  rt )continue ; 
        dfs ( v , cur ); 
        for ( int  j  =  p ; j > 1 ; j -- ) { 
        for ( int  k  =  1 ; k  <  j ; ++ k ) // divide into nodes under the subtree and itself 
        dp [ cur ][ j ] = min ( 
            dp [ cur ][ j ] , dp [ v ] [ k ] + dp [ cur ][ j - k ] - 2 ); 
        } 
    } 
    } 
    int  main () 
    { 
    cin >> n >> p ; 
    for ( int  a , b , i  =  1 ; i <= n - 1 ; i ++ ) { 
        cin>>a>>b;
        vv[ a ] .pb ( b ); 
        vv[ b ] .pb ( a ); 
    } 
    memset ( dp , INF , sizeof  dp ); 
    for ( int  i  =  1 ; i <= n ; i ++ ) dp [ i ] [ 1 ] =  vv [ i ]. size (); 
    dfs ( 1 , - 1); 
    int  ans  =  INF ; 
    for ( int  i = 1 ; i <= n ; i ++ ) ans = min ( dp [ i ][ p ], ans ); 
    cout  << ans  << endl ; 
    return  0 ; 
    }

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en3 English acash 2022-11-22 19:21:18 8 Tiny change: '**Doubt 1 ** **Is it incl' -> '**Doubt 1 Is it incl'
en2 English acash 2022-11-22 19:19:56 5 Tiny change: 'oted at v. **\n\n\nAc' -> 'oted at v.**\n\n\nAc'
en1 English acash 2022-11-22 19:18:45 2989 Initial revision (published)