HDU 3245-Treeland Exhibition (Tree DP)


HDU 3245-Treeland Exhibition (Tree DP)
Problem Description
There are n towns in the treeland – they form a tree, as you may guess, i.e. there is a unique path between every pair of towns. The length of road connecting every pair of adjacent towns is always 1 unit.

You want to hold an exhibition simultaneously on no more than L+1 consecutive towns, i.e. you choose two towns u and v of no more than L unit apart, and set up your exhibition in all the towns on the unique path from u to v. You want to attract people from all over the treeland to your exhibition, so you’d like to minimize the sum of “travelling distance” from every town. The “travelling distance” of a town is the distance from that town to its closest exhibition-town.
Input
There are at most 25 test cases. Each case begins with two integers, n and L (n <= 10000, 0 < L <= 100), the number of towns, and the maximal distance of the “endpoint towns” you choose. Next n-1 lines contain the descriptions of connections, each with two integers a and b, indicating that town a and town b are directly connected (towns are numbered from 0 to n-1). The input ends with n = L = 0.
Output
For each test case, print the minimal sum of travelling distance.
Sample Input
3 1 0 1 1 2 4 1 0 1 1 2 2 3 0 0
Sample Output
1 2

hdu 3245 zoj zju 3188 树形DP
首先明确一点,由于是两点之间的一条路径,所以不可能出现下面的情况

即不可能出现三叉路口,出现三叉的就不是两点间的路径了
所以只能是下面两种情况
1、         以u为根时,路径分布在u的两棵子树中,一棵子树中的长度为a,另一棵为
b=L-2-a,(图中红色的路径部分除外)

2、         只延伸出一条路径到一棵子树中

所以在v这棵子树中有L-1长度的路径存在。
我们先假设整棵树以0为根
Dp[u][i]表示以u为根的子树中路径长度为i时的最小代价,u为路径上的一个点,且为端点。 所以以0为根时的状态转移方程为
Dp[u][i]=min(dp[u][i],dp[v][i-1]+sumw[u]-sumw[v]-sum[v]);
sum[u]表示u所在的子树总的点的个数,sumw[u]表示u所在的子树中每个点到u的距离之和,sumw[u]-sumw[v]-sum[v]表示在u的子树中,去掉v所在的子树之后其他子树的点到u的距离之和,因为u为端点,所以其他子树(去除v之后的子树)到路径上的最近点都是u这一点。
所以
dp[v][i-1]+sumw[u]-sumw[v]-sum[v]代表的是分配给v这棵子树i-1长度的路径,u->v相连时的代价,如果这个代价比原先dp[u][i]要小,就更新。
子树有两种选择,取或不取,相当于01背包中每件物品的取或不取。
当然每个节点都有可能为整棵树的根,所以上面的过程只是求出了以0为根时的最少代价ans[0],0在路径上,
所以接下来以每个点(u)为根求这个点为路径上的一点时的最小代价 ,记为ans[u]。
对于每个点为根时的情况,就是我开头画的2、3两张图中情况了

第二步中,还是利用sumw[u]-sumw[v]-sum[v](u为根)把v这棵子树去掉,即有一部分路径在v子树中,再加上个dp[v][a]就表示分配给v子树长度为a的路径时最小代价,即sumw[u]+ dp[v][a]-sumw[v]-sum[v],所以dp[v][a]-sumw[v]-sum[v]越小越好,所以可以增加一个tmp[a]数组记录在u的某个子树中最多分配a长度的路径时dp[v][a]-sumw[v]-sum[v]的最小值,并随时更新。
const int maxn = 10010;
const int INF = 1000000000;
int dp[maxn][110];
int sum[maxn],sumd[maxn];
int head[maxn];
struct Edge{
    int v,next;
}edge[2*maxn];int N,L,E;
void add_edge(int a,int b)
{
    edge[E].v=b;
    edge[E].next=head[a];
    head[a]=E++;
}
void dfs(int u,int fa)
{
    int i,j,k,v;
    sum[u]=1;sumd[u]=0;
    fill(dp[u],dp[u]+L+1,INF);
    for(i=head[u];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if(v==fa) continue;
        dfs(v,u);
        sumd[u]+=sumd[v]+sum[v];
        sum[u]+=sum[v];
    }
    dp[u][0]=sumd[u];
    for(i=head[u];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if(v==fa) continue;
        for(j=1;j<=L;j++)
            dp[u][j]=min(dp[u][j],dp[v][j-1]+sumd[u]-sumd[v]-sum[v]);
    }
}
int ans[maxn];
void solve(int u,int fa)
{
    int i,a,v;
    if(u==0) ans[u]=sumd[0];
    else ans[u]=N-sum[u]+sumd[fa]-sum[u];
    int tmp[110];
    fill(tmp,tmp+L+1,INF); 
    int mi=INF;
    for( i=head[u];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if(v==fa) continue;
        for( a=0;a<=L-2;a++)
            mi=min(mi,tmp[L-2-a]+dp[v][a]-sumd[v]-sum[v]);
        for( a=0;a<=L-1;a++)
        {
            tmp[a]=min(tmp[a],dp[v][a]-sumd[v]-sum[v]);
            if(a) tmp[a]=min(tmp[a],tmp[a-1]);//最多分配a,如果tmp[a-1]更优,就等于tmp[a-1]
        }
    }
    mi=min(mi,tmp[L-1]);
    sumd[u]=ans[u];
    ans[u]+=mi;
    for(i=head[u];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if(v==fa) continue;
        solve(v,u);
    }
}
int main()
{
    int i,j,k,a,b;
    while(scanf("%d%d",&N,&L),(N||L))
    {
        if(N==1) {puts("0");continue;}
        E=0;
        memset(head,-1,sizeof(head));
        for(i=0;i<N-1;i++)
        {
            scanf("%d%d",&a,&b);
            add_edge(a,b);
            add_edge(b,a);
        }
        dfs(0,0);
        solve(0,0);
        printf("%d\n",*min_element(ans,ans+N));
    }
    return 0;
}

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts