Question link: http://acm.hdu.edu.cn/showproblem.php? PID = 1, 4003
Given a tree with N nodes, traversing each number of edges requires cost. Now, given K robots, we need to use these K robots to traverse the entire tree, minimum and cost, n <= 10000.
Solution: tree-like DP + grouping backpack. The grouping backpack in this question is not a general choice of at most one item, but must be selected and can only be selected. The specific analysis will be conducted later. After thinking for a long time, I first thought about the greedy solution. If K is 1, I just need to find the path from the leaves to the root cost and the largest one, expand to find the top K paths, can they be solved? The answer is no. Because the paths can overlap, there is no way to do this. After the idea was denied, I began to think about using the idea of dynamic regulation to solve this problem.
It is known that the status of the parent node is only transferred from the child node, and the problem is ineffective. tree-like DP is available. Each node has several sub-nodes, and each sub-node can choose 0-J robots (0 indicates that the robot taking this branch has already passed through other branches ), in this way, a model can be converted. Each subnode must be selected, so each group of items must be selected, but only one item can be selected, apparently!
When DP [I] [J] is set, node I uses J robots to traverse all its sub-nodes. Because each node has to go, there are two ways for each node to go: one is that the robot does not return to this point after it leaves, and the other is that the robot returns to this point after it leaves, therefore, j = 0 and j> 0 are used. After several robots enter a branch, if they want to return, only one robot will return. Assume that there are two slave v nodes, and the 4 * P-> V-> Cost + is spent for traversing the tree with p-> V as the root, however, only 2 * P-> V-> Vost + is required to traverse the tree with p-> V as the root, for example, the edge has ), take 1 as the root, then each side will traverse twice and return to 1 point, and the two (1, 2) will traverse four times.
The state transition equation is: DP [I] [J] = min (DP [I] [J-1] + dp [son] [0] + cost, DP [I] [J] + dp [son] [0] + 2 * cost)
DP [I] [J] = min (DP [I] [J], DP [son] [k] + dp [I] [J-K] + K * cost); // The cost is the edge (I, son) fee, and K is the state of the subnode.
This topic is a typical tree-like DP + backpack. We strongly recommend that you absorb it. The code can be constantly optimized. In my code, the state transition equation can be simpler, but I think it should be better to write and understand it. The Code ran for 234 Ms and ranked first in the top rankings.
Test data:
5 1 2
1 2 2
1 3 2
2 4 2
2 5 2
5 1 2
1 2 2
1 3 2
2 4 10
2 5 10
3 1 1
1 2 1
1 3 1
3 1 2
1 2 1
1 3 1
7 1 2
1 2 2
1 3 2
2 4 2
2 5 2
3 6 10
3 7 10
9 1 1
1 2 2
1 3 2
2 4 2
2 5 2
3 6 10
3 7 10
4 8 20
4 9 20
7 1 3
1 2 100
1 4 100
1 3 2
3 5 1
3 6 1
3 7 1
8 1 3
1 8 100
1 2 100
1 4 100
1 3 2
3 5 1
3 6 1
3 7 1
8 1 3
1 8 100
1 2 100
1 4 100
1 3 2
3 5 100
3 6 100
3 7 100
7 1 3
1 2 100
1 4 100
1 3 2
3 5 1000
3 6 100
3 7 1000
Code:
# Include <stdio. h> # include <string. h> # define Max 11000 # define min (a, B) (a) <(B )? (A) :( B) struct node {int V, cost; node * Next;} * head [Max * 2], tree [Max * 2]; int PTR, ANS, root, vis [Max]; int n, m, DP [Max] [12]; void initial () {PTR = 1; memset (DP, 0, sizeof (DP); memset (VIS, 0, sizeof (VIS); memset (Head, null, sizeof (head);} void addedge (int x, int y, int cost) {tree [PTR]. V = Y, tree [PTR]. cost = cost; tree [PTR]. next = head [X], head [x] = & tree [PTR ++]; tree [PTR]. V = x, tree [PTR]. cost = cost; tree [PTR]. next = head [Y], head [y] = & tree [PTR ++];} void tree_dp (INT v) {If (vis [v]) return; vis [v] = 1; int I, j, fir, SEC; node * P = head [v]; while (P! = NULL) {If (! Vis [p-> V]) {tree_dp (p-> V); For (j = m; j> = 1; -- J) {FIR = DP [v] [J-1] + dp [p-> V] [0] + P-> cost; // assign a robot to run the branch p-> V, the choice of FIR and SEC ensures that an item required by this group of backpacks is sec = DP [v] [J] + dp [p-> V] [0] + 2 * P-> cost; // other branches run the p-> V branch, and the DP [v] [J] = min (FIR, Sec) is run ); for (I = 1; I <= J; ++ I) DP [v] [J] = min (DP [v] [J], DP [p-> V] [I] + dp [v] [J-I] + I * P-> cost );} DP [v] [0] + = DP [p-> V] [0] + 2 * P-> cost; // This is equivalent to additional computing, this is used only in the first four sentences. In fact, robots are not allocated to run in this branch} p = p-> next ;}} Int main () {int I, J, K, A, B, C; while (scanf ("% d", & N, & root, & M )! = EOF) {initial (); for (I = 1; I <n; ++ I) {scanf ("% d", & A, & B, & C); addedge (A, B, C);} tree_dp (Root); printf ("% d \ n", DP [root] [m]);}
This article is original in zeroclock, but it can be reproduced, because we are brothers.