SRM 730, D1, 500-Pointer (Subgraphs)

James S. Plank

Sat Sep 1 00:43:30 EDT 2018
This one is more about figuring out the problem than the programming, although my solution was a straightforward dynamic program.

I'm not going to include any drawings here, sorry. If you are giving this problem in CS494/594, you should draw a bunch of graphs to help give some intuition about the problem and its solution.

So, when I started on this problem, I took pencil to paper and drew a bunch of graphs. I came to the following realizations:

Given those realizations, it came upon me that if I connect the second of the two nodes to every one of the nodes in the graph for k-1, then I have solved the problem! If I need to find a set that has exactly e edges, and e > (k-1)(k-2)/2, then I use the set from the solution for k-1 that has e-(k-1) edges, and add the second of the two nodes to the set. You'll note that the solution for k-1 has k-1 nodes. By adding the second node to the set, my set has k nodes, which is what we want, and I've just added k-1 edges to the graph, giving me a total of e edges. How cool is that!
So, the solution works as follows. Let G(k) be the graph for k. And let S(n,k) be the set of nodes in G(k) that has exactly n edges. Your goal is, given a value of k to define G(k) and then to find S(n,k) for every value of n from 0 to k(k-1)/2.

We start with a base case, where k = 1. In that case, k(k-1)/2 equals 0, so you only care about finding G(1) and S(0,1). The solution to this is simple -- G(1) is a single node with no edges, and S(0,1) is that node.

Now we attack the general problem.

We assume that we have solved the problem for k-1. Then, G(k) equals G(k-1) plus two new nodes, which I'll call lk and hk. There are no edges coming out of lk. On the flip side, hk has an edge to every other node in the graph except lk.

That's the graph. Let's turn our attention to S(n,k). Suppose that n ≤ (k-1)*(k-2)/2. Then S(n,k) = S(n,k-1){ lk }. Otherwise, S(n,k) = S(n-(k-1),k-1){ hk }. Man, that's awesome.

When I programmed this, I rendered the previous paragraph as a dynamic program, and memoized. It passed the topcoder system tests easily.

OK, if you're reading this because you need to present this in CS594, you had better be drawing a lot of pictures. You should draw G(k) for k ≤ 4, and show how you get S(n,k) from S(n,k-1) or from S(n-(k-1),k-1) pictorally. It's a challenging problem to present, but with good graphics, this will be a really fun problem to present!


And while I'm at it, when you're trying to figure out the running time of the program, ask yourself how the number of characters in the return value scales with k. Are you doing O(1) work for each character in the return value?