Subtask 1: T=0
First, root the tree at node 1. It is first important to observe that the order of visited pastures is similar to one of a DFS starting at node 1. This is because a DFS order minimizes the total amount of time to visit all pastures. The length a path traversed by a DFS is exactly 2(n−1), as it crosses each edge exactly twice. Because each edge must be crossed at least twice to visit the nodes in its subtree, this is a lower bound on the amount of time necessary, proving its optimality.
With this observation, what remains is to determine the order that Farmer John visits the children of each node. Note that once this order is determined for every node, the DFS order (and therefore the order that the pastures are visited) is uniquely determined.
Define dpu as the minimum amount of fertilizer necessary to fertilize all pastures in the subtree of u, such that the path starts at node u at time t=0, and also ends at node u. Let sizeu be the size of the subtree of node u, and sumu be the sum of ax over all nodes x in the subtree of u.
If Farmer John visits the subtree of child v at time t, it takes dpv+sumv⋅t fertilizer. This is because, during the first t seconds, the value of each pasture x in the subtree of v increased by av. With this in mind, consider a fixed order of the children of node u, call it v1,v2,…vk. The contribution of node vi to dpu in a particular order is dpvi+sumvi⋅(1+i−1∑j=02⋅sizevj). This directly follows from the previous observations, as the amount of time it takes to visit the subtree of child v is 2⋅(sizev−1)+2=2⋅sizev (the extra 2 comes from the time it takes to cross the edge (u,v)), with the 1 coming from crossing the edge (u,vi). Therefore, we need to minimize the sum of this quantity over all permutations of v1,v2,…vk.
Note that the sum of dpvi is constant, regardless of the order of the children, as is the sum of sumvi⋅1. After moving the 2 out of the summation, what remains is to minimize sumvi⋅i−1∑j=0sizevj. Consider the case where there are two children: v1 and v2. If v1 is placed before v2, the value of the expression is sumv1⋅0+sumv2⋅sizev1=sumv2⋅sizev1. Similarly, if v2 is placed before v1, the value of the expression is sumv1⋅sizev2. Placing v1 before v2 is therefore optimal if sumv2⋅sizev1≤sumv1⋅sizev2, or equivalently sizev1sumv1≤sizev2sumv2. To complete the solution, we must make use of an exchange argument. Consider an optimal ordering of the children. Consider some adjacent pair of children v1 and v2. Using a similar argument as above, we can show that if sizev1sumv1≥sizev2sumv2, we can swap the order of children and the cost would improve or stay the same. Therefore, an optimal solution must be sorted in non-decreasing order of sizevisumvi, completing the solution.
Subtask 2: T=1
The first key difference in this problem is that the minimum amount of time to visit the pastures is no longer always 2(n−1). Recall that earlier, Farmer John had to pass through each edge at least 2 times. However, let the last node that Farmer John visits be v. Farmer John only has to pass through the edges on the path from 1 to v exactly once. The number of these edges is exactly the depth of v in the tree. Therefore, the amount of time it will take him is 2(n−1)−depthv, so he must maximize the depth of the final node in his path.
For each subtree, calculate a second dp value pdu, defined similarly to the initial dp with the extra restriction that it must end on a node with maximum depth in the subtree. The answer to the problem is pd1.
To calculate pdu, iterate over the child v that is put last in the order (making sure to only check nodes with maximum depth in their subtree). Note that, from the same argument as earlier, the ordering for the rest of the nodes can be determined. Let's compute the difference between dpu and the cost of moving node v to the end of the order. The contribution of v to the sum becomes pdv+sumv⋅number of children−1∑i=02⋅sizevi, which can be computed in constant time. The values of the children who initially appeared before node v in the order remain the same, and the values of the children who appeared after node v decrease by 2⋅sumi⋅sizev. This value can be computed with a simple suffix sum, allowing us to calculate the value in constant time, allowing us to calculate pd in linear time, solving the problem.
Danny Mittal's code:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; public class FertilizingPastures { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer tokenizer = new StringTokenizer(in.readLine()); int n = Integer.parseInt(tokenizer.nextToken()); int t = Integer.parseInt(tokenizer.nextToken()); int[] parents = new int[n + 1]; List<Integer>[] children = new List[n + 1]; children[1] = new ArrayList<>(); long[] subtrees = new long[n + 1]; long[] rateSums = new long[n + 1]; for (int a = 2; a <= n; a++) { tokenizer = new StringTokenizer(in.readLine()); parents[a] = Integer.parseInt(tokenizer.nextToken()); children[parents[a]].add(a); rateSums[a] = Long.parseLong(tokenizer.nextToken()); children[a] = new ArrayList<>(); } long[][] dp = new long[2][n + 1]; int[] mostEdgesSaved = new int[n + 1]; for (int a = n; a > 0; a--) { subtrees[a] = 1; for (int b : children[a]) { subtrees[a] += subtrees[b]; rateSums[a] += rateSums[b]; dp[0][a] += dp[0][b]; mostEdgesSaved[a] = Math.max(mostEdgesSaved[a], mostEdgesSaved[b] + 1); } children[a].sort((b, c) -> Long.compare(rateSums[b] * subtrees[c], rateSums[c] * subtrees[b])); long currRateSum = 0; for (int b : children[a]) { dp[0][a] += (2L * subtrees[b]) * currRateSum; currRateSum += rateSums[b]; } dp[0][a] += currRateSum; if (!children[a].isEmpty()) { dp[1][a] = Long.MAX_VALUE; currRateSum = 0; long currEdgesTravelled = 0; for (int b : children[a]) { if (mostEdgesSaved[b] + 1 == mostEdgesSaved[a]) { dp[1][a] = Math.min(dp[1][a], dp[0][a] - ((2L * subtrees[b]) * currRateSum) + (currEdgesTravelled * rateSums[b]) - dp[0][b] + dp[1][b]); } currRateSum += rateSums[b]; currEdgesTravelled += 2L * subtrees[b]; } } } if (t == 0) { System.out.println((2 * (n - 1)) + " " + dp[0][1]); } else { System.out.println(((2 * (n - 1)) - mostEdgesSaved[1]) + " " + dp[1][1]); } } }