Sunday, October 18, 2015

A week with 13x30

Codeforces Round 325 was the first of two Codeforces rounds this week (problems, results, top 5 on the left). Um_nik has won his second Codeforces round thanks to finishing five problems with more than 30 minutes to go - impressive! Of course, subscriber's bug in problem A has also contributed - better luck next time for him.

TopCoder SRM 671 took place on Wednesday (problems, results, top 5 on the left). The top 5 of the round matched the current top 5 by rating almost exactly - just Burunduk1 did not participate, and snuke has managed to grab the fourth place instead.

I think such high correlation might be due to the fact that the hard problem was an interesting application of advanced dynamic programming, a very "professional" problem. Consider a grid with 13 rows and 30 columns, with each cell having an arrow pointing either right or down. We go row-by-row starting from the top row, and within each row we go column-by-column starting from the left column, and place dominos (2x1 tiles) on the grid. Whenever we encounter a cell without a domino, we look at its arrow. If it's pointing to the right, and there's an empty cell to the right, we place a domino on those two cells. If it's pointing down and there's an empty cell down, we place a domino on those two cells. If there's no empty cell in the direction of the arrow, we try the other direction (down for right, and right for down). If both directions don't work, we don't place any domino on this cell. Assuming the direction of all arrows is picked uniformly randomly out of all 213*30 possibilities, what's the expected number of placed dominoes at the end of this process?

Had the grid 13 columns and 30 rows, the dynamic programming would be pretty standard. But how do we deal with the transposed grid?

Codeforces Round 326 happened one day later (problems, results, top 5 on the left). With this victory, qwer continued his rocket-like rise through the rankings, with four new "titles" in last four rounds - I'm wondering what comes next :)

Finally, this week had quite a few important ACM ICPC selection rounds. ACM ICPC 2015-16 NEERC Southern subregional (problems, merged results, top 5 on the left, onsite results), together with an online contest on the same problemset three days later, gave us a chance to compare curent ACM ICPC teams where at least some of them were in real competition mode. Moscow State University team Trinity came out on top this time, getting problem M accepted with just 1 minute to go.

Does anybody know if team Excited who placed second is a real ACM ICPC team this year?

ACM ICPC 2015-16 NEERC Moscow subregional and SEERC still haven't published the results, so I'll come back to them next week.

And finally, let's come back to the Running City urban orienteering puzzles I've published in my last post.

The first one was:
1 + 6 = 7
1 + 3 = 2
3 + 6 = 4
4 + 6 = 5
Find a house with bas-relief sculptures at the northern end of the 4th. How many bas-reliefs with sheafs are there on the street facade?

The number referred to colors of the rainbow, and addition stood for mixing two paint colors: red + indigo = violet, and so on. "The 4th" referred to the Green street, or улица Зелёная.

The second one was:
The older brother got a highway, a street, and an alley (albeit an old-fashioned one). The middle sister got an avenue and a street, not too bad as well. The younger brother, however, got just one little alley. Find house number 6 on the younger brother's alley, and count the number of mosaics on the facade.

Here, the answer was the capitals of the Baltic states: there are Tallinn highway, Tallinn street, Reval (the old name of Tallinn) alley, Riga avenue, Riga street and Vilnius alley in St. Petersburg. When solving this puzzle, our team employed programming: we've parsed a list of all streets of St. Petersburg, and found the intersection of the highway and street names which turned out to be surprisingly small, then looked at them one by one until Tallinn "clicked".

Thanks for reading, and check back next week!

Saturday, October 17, 2015

A week with sheafs

The biggest contest of last week for me was not a programming one: Running City 2015 took place in Saint Petersburg on Saturday (Bronevik-pro category: problems in Russian, results in Russian, top 5 on the left, all categories: problems in Russian, winners in Russian). This is an urban orienteering contest, where teams compete against one another to visit as many control points in the city as possible as fast as possible. However, it's not just about running, commuting or driving: first, the organizers try to pick interesting control points, so that you see interesting places and learn a lot about the city, so it's also a sightseeing tour in a sense. More importantly (at least for me), some control points are not simply given to you on the map or as a street adress; instead, they are given to you as puzzles. Only after solving the puzzle you know where you should go.

The puzzles are in Russian and often involve play on Russian words and/or Russian cultural context, but here's one from this year's contest that's somewhat international:

1 + 6 = 7
1 + 3 = 2
3 + 6 = 4
4 + 6 = 5
Find a house with bas-relief sculptures at the northern end of the 4th. How many bas-reliefs with sheafs are there on the street facade?

Here "4th" refers to a street, but not literally called "4th", but rather referring to "4" in the equations above. Counting bas-reliefs with sheafs serves two purposes: first, it's a good way to prove that you've actually found the right spot in the city that doesn't require a judge to always be there, and second, it helps you verify that your solution to the puzzle is correct - if there are no bas-reliefs with sheafs in the place you come to, you need to think again :)

Here's another puzzle from this year's contest, which requires more local knowledge, but at the same time is more typical for the contest as it requires to match one's ideas with the actual city streets:

The older brother got a highway, a street, and an alley (albeit an old-fashioned one). The middle sister got an avenue and a street, not too bad as well. The younger brother, however, got just one little alley. Find house number 6 on the younger brother's alley, and count the number of mosaics on the facade.

The competition has a lot of categories, differing in difficulty (some require just 4-5 hours, some 10+), allowed means of transportation (only walking, walking and running, public transportation, no restrictions which effectively means driving), and the style of control points (given as an address, or as a puzzle). I'm usually participating in the difficult no-transportation-restrictions all-control-points-as-puzzles category, called "Bronevik-pro", but I think it's great that they provide categories to everybody's taste - i.e., I can totally understand how many competitors find it exciting to look for ways to find creative ways of using public transportation and the best order of passing control points in the "Atlant" category.

Most of their competitions happen in Russia, but they do have some international presense (planned for 2016: Helsinki, Milan, Istanbul), and to the best of my knowledge the international competitions have some categories in English, so if you notice your city on the event list, I think it's worth participating in :)

TopCoder SRM 670 took place during the Running City (problems, results, top 5 on the left). In addition to the highest score from coding, tourist has managed to gain +150 from challenges, although it turned out to be not even necessary for this vey convincing victory - great job!

Sunday was the day for Open Cup 2014-15 Grand Prix of SPb (results, top 5 on the left), The Nizhny Novgorod SU team has won their second Grand Prix of the season, matching Past Glory's achievements - way to go!

This round had many nice problems, but let me mention the most difficult one, problem C. Consider an undirected graph without repeated edges (but possibly with loops) with n vertices. Such graph is called Eulerian if and only if there's a cycle that traverses each edge exactly once. How many Eulerian graphs with n vertices exist, up to isomorphism? n is up to 60, you need to output the answer modulo 109+7.

Last week, I've mentioned an old problem that I couldn't understand my own solution for. The problem was: given an amount, and a set of coin denominations such that for every two denominations one divides the other evenly, how many ways are there to assemble the given amount?

After some time, I think I've figured my solution out :) Let's create a graph interpretation for our problem. We'll create a directed graph with n "layers", each layer corresponding to one coin denomination. For a layer corresponding to denomination x, there are vertices corresponding to amounts 0, x, 2x, ... For each vertex there's an arc to the next highest amount in the same layer. Additionally, for each vertex except those on the first layer there's an arc to the same amount on the previous layer - the one corresponding to the next smallest denomination. The picture on the left illustrates the graph corresponding to denominations 1, 2, 4 and 12.

We can notice now that the ways to assemble the required amount a correspond to the ways to go from vertex 0 on the n-th layer to vertex a on the first layer: every time we make a horizontal move inside the layer corresponding to denomination x, we take one coin of denomination x. Because we're only allowed to move horizontally or upwards, we will enumerate the coins in non-increasing order, and thus each way to assemble the required amount will be counted exactly once.

Now we'll use dynamic programming to find the number of ways to reach amount p on layer q. To transition from amount p to amount p+1, we need to consider horizontal movement, which doesn't change the layer, and also upwards movement, which means we should add the number of ways to reach layer q to the number of ways to reach each smaller layer, assuming layer q has a vertex at the amount p+1. If we write all answers for one p as a vector, transitioning from p to p+1 corresponds to multiplying this vector by a matrix, and there are n different matrices in play, depending on the highest denomination that divides p+1. Finally, fast matrix exponentiation allows us to multiply those matrices fast enough.

Hopefully the code (requires TopCoder login) makes more sense now:
public int solve(long coins_sum, long[] values) {
    int n = values.length;
    long[][][] oneCycle = new long[n][][];
    oneCycle[0] = unitMatrix(n);
    for (int i = 1; i < n; ++i) {
        long curBy = values[i] / values[i - 1];
        oneCycle[i] = multiply(extraMatrix(n, i), pow(oneCycle[i - 1], curBy));
    }
    long[][] total = unitMatrix(n);
    for (int i = n - 1; i >= 0; --i) {
        long fullCycles = coins_sum / values[i];
        coins_sum %= values[i];
        total = multiply(pow(oneCycle[i], fullCycles), total);
    }
    long res = 0;
    for (long x : total[0])
        res += x;
    return (int) (res % MODULO);
}

private long[][] extraMatrix(int n, int start) {
    long[][] res = unitMatrix(n);
    for (int i = 0; i < start; ++i)
        res[i][start] = 1;
    return res;
}

Thanks for reading, and check back tomorrow for this week's summary and for answers to the Running City puzzles!

A week with old self

// This post is for Sep 28 - Oct 4 week. I'm sorry for the delay!

Monday was the day of TopCoder SRM 669 (problems, results, top 5 on the left, Egor's screencast). It would seem that Egor has found renewed motivation in my publishing of his screencasts in this blog: two weeks ago he jumped onto the leaving TopCoder Open train during the challenge phase, and this time he won the SRM easily - great job!

The most interesting aspect of this match for me was about the hard problem. You're given an infinite amount of coins of each denomination from 1, M, M2, M3, ..., and a given amount X, up to 1018. M is up to 1000. How many ways are there to assemble this amount using the given coin types?

I didn't have much time left for this problem, but I also didn't have any good ideas how to approach it. After the match has ended, we've found out that a more difficult version of this problem has appeared in SRM 527 four years ago: in that problem, the denominations were not fixed to powers of a single integer, and the only constraint was that for every two denominations one divided the other evenly. Back in 2011, both I and Egor have solved the problem, but neither I nor him remembered anything about it :)

That's when things started to be a little surreal. I've opened my solution (requires TopCoder login) from that match - and I couldn't understand how it worked! After some time and effort, I've finally figured it out, and I'll tell more in the next week's summary - but in the meantime, can you understand it? Here's the main part of the code:

public int solve(long coins_sum, long[] values) {
    int n = values.length;
    long[][][] oneCycle = new long[n][][];
    oneCycle[0] = unitMatrix(n);
    for (int i = 1; i < n; ++i) {
        long curBy = values[i] / values[i - 1];
        oneCycle[i] = multiply(extraMatrix(n, i), pow(oneCycle[i - 1], curBy));
    }
    long[][] total = unitMatrix(n);
    for (int i = n - 1; i >= 0; --i) {
        long fullCycles = coins_sum / values[i];
        coins_sum %= values[i];
        total = multiply(pow(oneCycle[i], fullCycles), total);
    }
    long res = 0;
    for (long x : total[0])
        res += x;
    return (int) (res % MODULO);
}

private long[][] extraMatrix(int n, int start) {
    long[][] res = unitMatrix(n);
    for (int i = 0; i < start; ++i)
        res[i][start] = 1;
    return res;
}

Codeforces Round 323 took place on Saturday (problems, results, top 5 on the left). Ecnerwal has continued his great form that helped him qualify for the TopCoder Open, and won this round, but both ikatanic and uwi finished extremely close, within 7 points of the first place - congratulations to all three!

And finally, Open Cup 2015-16 Round 3, the Grand Prix of Eurasia, happened on Sunday (problems, results, top 5 on the left). The problemset was mostly easy, but still team Past Glory has achieved an amazing feat, solving the first 10 problems in just 1 hour and 23 minutes! Of course, winning the round after that was almost guaranteed. Congratulations!

Thanks for reading, and check back tomorrow for last week's summary!

Thursday, October 1, 2015

A week with a Japanese surprise

The Open Cup held a surprise second round, the Grand Prix of Japan, last Sunday (results, top 5 on the left, overall standings). Past Glory team returned to, well, past glory with a very convincing victory - congratulations!

Problem B, while not very difficult algorithmically, presented a nice implementation challenge: one could write the code in 10 minutes, but could also spend an hour or more. You were given 3000 boosters with integer coordinates up to 109, each pointing in one of four cardinal directions. You can start at any booster, fly in the direction in points to the next booster (if any), then fly in the direction that booster points, and so on. As soon as you leave a booster, it disappears, so you don't change your direction when you pass through its point again. What is the maximum number of boosters you can visit if you choose your starting booster properly?

In my previous post, I've mentioned the medium problem from TCO 2015 Round 3B: you are given 200000 cookies (3 types pictured on the left), with two players taking those cookies in turn one by one. Each cookie has some value for the first player, and some possibly different value for the second player. It is known that the second player always takes the cookie with highest value for him, and when there are several, with the highest value for the first player among those. The first player, on the other hand, is more flexible. He can take any cookie, and his goal is to maximize the total value of the cookies he gets in the end to him minus the total value of the cookies the second player gets in the end to the second player. What is the optimal strategy for the first player?

I won't tell you the full solution, but I will give you a key hint. Let's forget about the goal of the first player, and simply ask ourselves: which subsets of cookies can he achieve? Let's also order the cookies by second player's priorities: first by decreasing value for the second player, then by decreasing value for the first player. It's clear now that the second player will take either the first or the second cookie in this order on the first move, one of the first four cookies on the second move, and so on. In fact, the first player can achieve any subset that has the following properties: at most one cookie from the first two, at most two cookies from the first four, at most three cookies from the first six, and so on.

This is not the full solution yet, but we've effectively removed the game from the problem - now we just have a question about some subsets of our set, and this question is much easier to answer.

Thanks for reading, and check back next week!

Thursday, September 24, 2015

A week with another 6

TopCoder SRM 668 was the first contest on the week in the early hours of Wednesday (problems, results, top 5 on the left). ACRush was the highest-rated competitor, most probably practicing before the upcoming final TCO elimination round. He has placed 6th, which is exactly the last qualifying spot in the TCO - but would he be able to repeat this performance in the TCO round? Read until the end of this post to find out :)

Enot was the winner of this SRM and the only contestant to solve all 3 problems - very impressive! This is his first SRM victory, maybe the streams have helped him improve?

Codeforces Round 320 (Bayan Thanks-Round) took place a few hours later (problems, results, top 5 on the left). Quite a few contestants have managed to solve 5 problems out of 6, so in order to win one also needed to find a few bugs in solutions of competitors. Um_nik and Egor have excelled on this front with +500 points each, but Um_nik had slightly more points from his solutions and has claimed the victory - congratulations!

Russian Code Cup 2015 Finals was one of the "major" tournaments of the year, with $4500 up for grabs for the first place (problems in Russian, results, top 5 on the left, broadcast with commentary in Russian). The problemsetters seem to have been worried about contestants finishing early, and made the last two problems just a tiny bit too hard - quite a few contestants were close on E, and I've found out after the analysis has been published that my solution on F was not that far from the correct one, but nobody could get either problem accepted.

Problem D was a nice logical puzzle: you are given 200000 points on the coordinate plane, and want to find two points such that their bounding box has a positive area, but does not contain any other points inside or on the border, or report that there's no such pair. After solving the "yes/no" part, don't forget to also think about finding the specific pair :)

And finally, TopCoder Open 2015 Round 3B determined the last 6 participants of one more major tournament (problems, results, top 6 on the left, my screencast, Egor's screencast). Scott_wu has won with comfortable margin, but the most exciting aspect for me as a viewer was Egor's climb into the qualifying zone during the challenge phase - here's the direct link into the critical moment of his screencast.

The medium problem was the nicest in my opinion. You were given 200000 cookies, with two players taking those cookies in turn one by one. Each cookie has some value for the first player, and some possibly different value for the second player. It is known that the second player always takes the cookie with highest value for him, and when there are several, with the highest value for the first player among those. The first player, on the other hand, is more flexible. He can take any cookie, and his goal is to maximize the total value of the cookies he gets in the end to him minus the total value of the cookies the second player gets in the end to the second player. What is the optimal strategy for the first player?

Now we know the 12 finalists of TopCoder Open 2015. There's a very heavy skew towards the ex-USSR this time:
Russian Federation - 7: Petr, UdH-WiNGeR, qwerty787788, kuniavski, Egor, Kankuro, Endagorion
Belarus - 2: tourist, subscriber
United States - 2: scott_wu, ecnerwal
South Africa - 1: bmerry

Thanks for reading, and check back next week!

Tuesday, September 15, 2015

A week with Gambler's Ruin

Codeforces Round 319 took place on Thursday (problems, results, top 5 on the left, solution analysis). I did not take part, but I heard that the problems were somewhat different in style from the last round - and yet the people in the first two places are the same. Huge congratulations to Marcin_smu and mnbvmar!

TopCoder SRM 667 happened one day later (problems, results, top 5 on the left, my screencast). The round was very tricky, with 250 inviting a lot of incorrect greedy solutions, the 500 requiring a lot of careful mathematical reasoning, and 1000 being a "constructive" problem which was hard to even approach.

W4yneb0t would be a clear winner thanks to his correct solution for the 1000 - if not for the challenge phase, where K.A.D.R found 10 incorrect solutions for the 250 and managed to climb to the first place despite solving only the easiest problem - great job!

Coming up with a good challenge case wasn't easy at all. Here's what the problem was about: you have 20 skills to learn and 50 exercises, each exercise will give you a certain subset of skills (the subset for each exercise is fixed, but can be different for different exercises). If there are k skills you don't have yet among the skills that the exercise gives you, then you spend k2 effort on that exercise. What is the minimum total effort you must spend to learn all skills? Naturally, the greedy solutions just picked an exercise that adds the smallest number of skills at each step. Can you see how to make them fail? I'm also wondering how did people come up with such testcases during the round - was stress-testing the way to go?

The careful mathematical reasoning in the 500 was basically about finding a closed form solution to gambler's ruin. Of course, since this is a well-known task, one could replace the mathematical reasoning with Googling, which I duly did. I didn't know the term "gambler's ruin", though, so you can watch how I gradually converged to the right search terms starting from this moment of the screencast :)

Open Cup 2015-16 Grand Prix of Ukraine has ignited the new season of the Open Cup on Sunday (results, top 5 on the left). Quite a few veteran teams participated, but the first place still went to a team that will participate in ACM ICPC this year - great job, NNSU!

Problem K, while being quite standard, allowed one to practice various dynamic programming techniques from this blog post. It went like this: you are given N numbers, and need to split them into M consecutive groups. The first number in each group is multiplied by 1, the second number in each group is multiplied by 2, and so on, and you need to minimize the sum of those products. And of course, you need a solution that's faster than O(N3).

During the contest, my teammate Ilya got the divide and conquer approach accepted, after the contest I've solved it using something similar to Knuth's optimization in upsolving, and the post-match discussion mentions that convex hull optimization also worked well :)

Finally, let me come back to the 4x4 problem from last week, counting the number of AxB rectangles of 0s and 1s such that each CxD subrectangle contains the same number of 1s. C and D are up to 4, so the subrectangle is very small, but A and B are up to a billion.

The solution is a classical case of gradually simplifying the problem until it becomes tractable. The first step is: let's try to gather some more knowledge from the fact that each CxD subrectangle has the same sum. More specifically, let's shift a CxD subrectangle to the right by 1. Now we can see that two 1xD columns that are C apart horizontally must also have the same sum.

Now let's shift those two 1xD columns down by 1. We can see that the differences between the corners are the same: a[x+C][y+D]-a[x+C][y]=a[x][y+D]-a[x][y]. Note that if this difference is not zero, then we can uniquely determine the values in the corners: for example, if the difference is 1, then a[x+C][y+D]=a[x][y+D]=1, and a[x+C][y]=a[x][y]=0. This, in turn, simply means that: if we have a[x][y] not equal to a[x][y+D], then all values in corresponding rows with step C are equal: a[x][y]=a[x+C][y]=a[x+2*C][y]=...=a[x-C][y]=a[x-2*C][y]=..., and the same for row y+D; a similar statement is true for columns.

At this point we can see that we've learned a lot about relations between cells that differ by a multiple of C horizontally and by a multiple of D vertically. In order to dissect the problem further, let's look at each such subgrid independently: take some offsets 0 <= c < C and 0 <= d < D, and consider all cells with coordinates (c+p*C,d+q*D). The above observation has a very concise meaning for this subgrid: whenever two horizontally adjacent cells in the subgrid have different values, the columns containing them are constant; and whenever two vertically adjacent cells in the subgrid have different values, the rows containing them are constant.

Now it's quite easy to make the next step: we can notice that the two situations (two constant rows and two constant colums) are mutually exclusive: if there's at least one constant row, then there can be no two constant columns with different values, and vice versa. This, in turn, simply means that there are just two possibilities for the entire subgrid: either all rows are constant (we will call such subgrids "horizontal"), or all columns are constant (we will call such subgrids "vertical"). Of course, a subgrid can be both horizonal and vertical at the same time, in case all values are equal.

Having learned the exact structure of each subgrid, it's time to go back to the full grid. It consists of C*D subgrids, each in the form described above. Let's look at the fact that two 1xD subrectangles that are C apart horizontally: they must have the same sum. They include cells from D different subgrids. The corresponding cells in horizontal subgrids are equal, so we can simply disregard them. The corresponding cells in vertical subgrids might not be equal, so we have some constraints on the vertical subgrids now. In a similar manner, looking at Cx1 subrectangles that are D apart vertically helps us get some constraints on the horizontal subgrids. Moreover, it's not hard to see that those constraints are not just necessary, but sufficient: if every two 1xD subrectangles that are C apart horizontally have the same sum, and every two Cx1 subrectangles that are D apart vertically have the same sum, then it's not hard to see that all CxD subrectangles have the same sum, too.

So we have reduced the original problem to making sense of the constraints induced on the horizontal/vertical subgrids. We can note that horizontal and vertical subgrids have independent constraints, so we can analyze them separately. Moreover, the vertical subgrids, for example, have constraints in groups of at most D, and each such group of at most D vertical subgrids is constrained independently, so it suffices just to analyze one of them.

And finally, we can see that the remaining problem is not hard anymore. We have a group of n <= D vertical subgrids, and we need the sum in each column to be the same. If this sum is m, then there are C(n,m) ways to pick one column, and thus C(n,m)t ways to pick all subgrids, where t is the number of columns (which is equal either to A/D or A/D+1, depending on the offset of the subgrid). Summing this over all values of m, we get the total number of ways to fill these n vertical subgrids.

All that's left is to multiply the answers for the independent problems we've solved to get the answer for the problem. Well, almost all :) In the above solution we relied on knowing which subgrids are vertical and which are horizontal. In reality, we don't know that, but we have just C*D <= 16 subgrids, so we can iterate over all 2C*D ways, compute the answer for each case, and add those up. 

This solution, will, however, count some grids twice: when a certain subgrid is constant, it is both vertical and horizontal, so we will count a grid containing such subgrid several times. In order to avoid that, we should remove constant subgrids from one of the sides, let's say from horizontal subgrids, and that will allow us to count each grid exactly once. In order to count the number of ways to fill a group of horizontal-but-not-constant subgrids, we have to use the inclusion-exclusion principle: start with the above computation that allows constant subgrids, subtract the number of ways to fill the grids such that one subgrid is constant, add the number of ways to fill the grids such that two subgrids are constant, and so on.

Finally, all loose ends are tied and we have a solution. Despite the length of the explanation, the code itself ends up being quite short. And the key idea, again, is to continue to simplify the problem in many small steps, and not give up early.

Thanks for reading (has anybody read this far?), and check back next week!

Monday, September 7, 2015

A week with 4x4

TopCoder Open 2015 Round 3A took place on Saturday (problems, results, top 6 on the left). First 6 places in the onsite competition in Indianapolis were handed out to those who could solve either the medium or the hard problem, with another 6 selected in Round 3B that will take place in two weeks. According to the official website, we will have a semifinal round and a final round onsite, but the number of advancers from the semifinal isn't known yet. A similar structure was used in 2009, with 18 onsite participants competing in a single semifinal and 8 qualifying to the final. Scaling that down to 12 onsite participants means we'd have 5 contestants in the final, but of course only TopCoder knows for sure.

The hard problem has left me stunned: how come such simple question has never been studied before, and yet requires a complex but doable solution? The problem simply asked about the number of AxB rectangles of 0s and 1s such that each CxD subrectangle contains the same number of 1s. C and D are up to 4, so the subrectangle is very small, but A and B are up to a billion.

Coming back to a problem I mentioned last week: given a tree and a vertex selected in it, what's the maximum number of different vertices a walk of a given length L starting from the given vertex can visit?

The main idea of the solution is that walks in a tree do not have a lot of freedom. More specifically, if a walk in a tree starts and ends in the same vertex, then it traverses each edge an even number of times - for each step "down" there's a corresponding step "up", which in turn means we traverse each edge either 0 times or at least twice. Because of this, a cyclic walk of length L visits at most L/2 different vertices in addition to the starting/ending vertex. Suppose now that the walk is not cyclic, going from some vertex A to another vertex B. Again, since walks in a tree do not have a lot of freedom, it's not hard to see that this walk can be represented as the direct walk from A to B along the tree, plus some cyclic walks inserted into it, so we get 1 new vertex per edge when walking from A to B, and 0.5 new vertices per edge when walking along the cycles, and the maximum number of different visited vertices is 1+d+(L-d)/2, where d is the distance between A and B. Now it's clear that we should simply pick B to be as far from A as possible, but at most L edges far.

Thanks for reading, and check back next week!