### Hints for SRM 576, D2, 500-Pointer (ArcadeManao)

### James S. Plank

Wed Oct 30 12:04:05 EDT 2013

Problem Statement.

Were I to give you a value of *L*, and ask you if Manao can get the coin, this would
be a very simple DFS problem. As always, with a DFS, you need to ask yourself what the best
way is to structure the graph. Here's what I suggest:
Create a graph from the problem specification, where each node contains two adjacency lists:
one for horizontal edges, and one for vertical edges. Horizontal edges are easy -- you can
be connected horizontally either to the cell on your left or your right. Vertical edges
are a little trickier. You should have a vertical edge to the first platform above you, and
the first platform below you.

For example, here would be the graph from the problem statement (Example 0):

Now, given a value of *L*, you can do a DFS to determine whether the starting node
is connected to the coin node. When you do your DFS, you do not traverse vertical edges
that are longer than *L*.

What's the running time complexity of that? Well, *|V|* and *|E|* are both
bounded by *MN*, so it is *O(MN)*.

If you do this for every value of *L* from 1 to *N*, then the running time
complexity is *O(N*^{2}M). In our constraints, the maximum value for
*N* and *M* is 50, so this value is 125,000, well within the constraints.

Give it a try.

### Two improvements

While these are not necessary for Topcoder, there are two improvements that you can do.
First is to perform a binary search on *L*. That is *O(NM log(N))*.
Second is to structure the problem differently. Instead, suppose you build the graph incrementally.
You start with a graph with all nodes and no edges. For example, here is Example 0:

Now, add all edges of size 1, and for each of these, determine connected components with
disjoint sets. You can treat the graph as undirected this time. Each time you add an
edge, you test to see if it connects nodes in different disjoint sets. If so, you perform
Union. When you are done with the edges of size 1, you see if the starting node and the
coin node are in the same disjoint set. Here's the graph after adding the edges of size 1:

The starting node and the coin are not in the same disjoint set, so you continue adding
edges of size two:

The starting node and the coin are in the same component. We're done, and *L=2*.

Now, what's the running time complexity of this? Well, we have to sort the edges,
which is *O(|E| log(|E|))*. Then we do up to *2|E|* find operations and up
to *|V|-1* union operations. That means:

*O(|E| log(|E|)) + O(|E|) + O(|V| α(|V|))*
The dominant cost here is sorting, so it is *O(|E| log(|E|))*.