CHEFGIRL - Editorial



Author: Dmytro Berezin
Tester: Sergey Kulik
Editorialist: Kevin Atienza


Dynamic programming, directed graphs


There is a directed acyclic graph representing people with the following properties:

  • All nodes have at most one incoming edge.
  • All nodes have at most one outgoing edge, except node 1.

Person 1 (node 1) holds 32 secrets, [1,32]. If there is an edge from a to b, then a tells secrets to b. But each edge has a range assigned to it, specifying the range of secrets that can be told “through” this edge.

If a node doesn’t have an outgoing edge, she tells all the secrets she knows to Chef.

The following operation can be performed: take some edge, and extend its range by one (to the left or the right). What is the minimum number of operations for Chef to know all 32 secrets?


The graph consists of paths all starting from node 1, and are otherwise disjoint aside from sharing node 1.

For each such path, and each range [i,j], compute the minimum number of operations to make sure all secrets [i,j] can be told through that path.

For all ranges [i,j], compute \text{cost}(i,j), defined as the minimum number of operations to make sure the secrets [i,j] reach Chef through a single path, among all paths.

Let \text{best}(k) be the minimum \sum_{[i,j] \in P} \text{cost}(i,j) among all partitions P of [1,k] into subranges. (For example P = \{[1,4],[5,9],[10,15]\} partitions [1,15].) The answer is \text{best}(32), and the $\text{best}(k)$s can be computed with dynamic programming, using the following recurrence:

\text{best}(k) = \min_{1 \le j \le k} \left[\text{best}(j-1) + \text{cost}(j,k) \right]


The property that all nodes must have at most incoming edge and at most one outgoing edge (except node 1) limits the possible shapes the input graph can be in. Essentially, there can’t be any sort of branching into or out of any node except node 1. This means that our graph is really just a bunch of disjoint paths all starting from node 1. (The problem statement doesn’t in fact exclude the possibility of there being paths that don’t start at node 1, but it seems these paths don’t appear in the input.) This makes things much easier for us, and also suggests looking at each path individually.

Consider a path from node 1 to some node with no outgoing edge. Thus, when a secret reaches the end of this path, it also reaches Chef. In fact, the secrets that can pass through this path are those that belong in the intersection of the ranges assigned to all the edges in the path. But the intersection of two ranges is another range! This means that the set of secrets that can be relayed in a path is always some range (possibly empty). In other words, if secrets a and b can be relayed through a path, then all secrets between a and b can also be.

This tells us that the way in which the secrets [1,32] are relayed to Chef is by relaying subranges of [1,32] through different paths until all secrets have reached Chef. For example, the subrange [11,24] might be relayed through one path, the subrange [28,29] through another path (or maybe the same path), and [23,26] in yet another, etc. But for all secrets to be sent, the subranges must cover the subrange [1,32].

Thus, it makes sense for us to compute the minimum number of operations to send the secrets [i,j] through some path, say p. Let’s denote this by “\text{cost}(p,i,j)”. For [i,j] to be able to pass through this path, we only need to make sure that [i,j] is contained in the ranges assigned to each edge of the path. It’s easy to see that this is necessary and sufficient. So for every range [a,b], we want to extend it so that it contains [i,j], which is equivalent to saying that a \le i \le j \le b. It’s easy to see that the minimum number of steps we need to accomplish this is \max(0,a-i) + \max(0,j-b):

  • \max(0,a-i) steps (extending [a,b] to the left) are needed to ensure that a \le i.
  • \max(0,j-b) steps (extending [a,b] to the right) are needed to ensure that j \le b.

Therefore, for a single path p and range [i,j] we can easily compute \text{cost}(p,i,j) by summing this value for all edges in p.

Now, we want to relay the secrets [1,32], and we have multiple paths to use. As said above, we know that we will send subranges through different paths, but things are a bit trickier because we don’t know yet where to send each subrange through so that the total cost is minimized. Thankfully, there are a couple of observations that will make our search easier:

  • We only need to send every secret at most once, so we can in fact assume that the set of subranges that cover [1,32] are disjoint. (Note that this doesn’t mean that there is only one way for a particular secret to reach Chef.) For example, suppose we send the subrange [8,15] through one path and [13,20] through another. These two subranges overlap, so we can replace the second with the smaller subrange [16,20]. Clearly, \text{cost}(p,16,20) cannot be greater than \text{cost}(p,13,20). (Why?)
  • It doesn’t make sense to send two disjoint subranges in the same path. Why? Consider for example sending [3,6] and [10,15] through some path p (assuming [7,9] are sent through other paths). However, remember from above that if two secrets can be relayed through a path, then all secrets in between them can also be, too. Thus, secrets in the range [7,9] can also be relayed here too (without incurring any additional cost)! This means we can assume instead that we are relaying [3,15] through p.
  • Finally, it doesn’t matter which path we send each subrange [i,j] through. We only want the path that minimizes the cost. For example, if \text{cost}(p_1,12,25) < \text{cost}(p_2,12,25), then we can essentially ignore path p_2 when sending [12,25] because there’s a way to send it with a smaller cost. (namely, through p_1) Thus, we can define the function \text{cost}(i,j) to be the minimum \text{cost}(p,i,j) among all paths p.

With these observations, the problem is now reduced to this:

What is the minimum \sum_{[i,j] \in P} \text{cost}(i,j) among all partitions P of [1,32] into subranges?

But this is easily solved with dynamic programming: Let \text{best}(k) be the minimum \sum_{[i,j] \in P} \text{cost}(i,j) among all partitions P of [1,k] into subranges. (For example \{[1,4],[5,9],[10,15]\} partitions [1,15].) Then the answer is \text{best}(32), and \text{best}(k) has the following recurrence:

\text{best}(k) = \min_{1 \le j \le k} \left[\text{best}(j-1) + \text{cost}(j,k) \right]

The j in this formula represents the leftmost endpoint of the rightmost range, [j,k]. The minimum total cost for the remaining subranges is \text{best}(j-1).

The base case is \text{best}(0) = 0. Thus, after computing the $\text{cost}(i,j)s for all ranges [i,j]$, 1 \le i \le j \le 32, the answer can now be computed easily using this DP solution!

Time Complexity:

O(NS^3) or O(NS^2) where S is the number of secrets. (S = 32)




This problem probably had weak test data, i don’t know why, i submitted a wrong solution and it was partially accepted for 30 pts.

It just failed on two tasks of the last subtask.


Greedy solution also passed.Why so?

The test cases were weak… even solution which take all pair’s of leaf nodes and calculate the answer passed the large tests.
I even posted a comment on the 6th day of the contest… it is yet to be approved by the admin.Such repeated lethargy by the codechef team is only ruining the image of the platform.
P.S. - The last such incident was in the previous cook-off.Wrong solutions passed the system tests for the first problem.Some people posted regarding it, but nothing was done…


Link to the code is broken. Kindly fix it.

1 Like

well the testcases were definitely weak i must say…
Because my this solution : -> passed for 90 points but it shouldnt since it failed for many testcases.
I was continously getting wrong answer for subtask 1.
then I made slight modification on my code ,and it passed subtask 1 but now was getting wrong answer for subtask 2.
here it is ->

I merged both of them and got 100 :smiley:
my 100 pt solution : - >

I really wanna know why this happened. :smiley: :slight_smile:


This problem can also be solved using Dijkstra’s shortest path algorithm using greedy approch.

Can anyone help me find out the cases I am missing.Here’s my code:
I first identified all the girls chef can take information from.Then I traversed from 1-32.And then I identified the girl which gives minimum steps for that particular secret.For that particular girl i altered its edge and the edges of the intermediate girls to get the secret,also if that provides chef other secrets i mark them as found and don’t perform the above procedure for them.The secrets are treated independently,for example, when i look for 7th secret i look for minimum steps to get only 7,not 1+2+…+7.

1 Like

@shubh_gupta_ can you please explain how to do it using dijkstra

nice editorial. :slight_smile: