I recently came across this (Edit: Problem A) interesting problem from Spotify's hacker challenge earlier this year which involves determining the switching at train truck junctions to route a train back to it's starting point. The train must arrive facing the same direction it left and the train can never reverse on the tracks.
As I understand it, the problem can be modeled as an undirected(?) graph where we must find the shortest cycle from a certain vertex, or detect that no such cycle exists. However, the interesting part is that for a vertex, v, the vertices adjacent to v are dependent on the path taken to v, so in a sense the graph could be considered directed, though this direction is path-dependent.
My first thought was to model each node as 3 separate vertices, A, B and C, where A <-> B and A <-> C, and then use a breadth-first search to build a search tree until we find the original vertex, but this is complicated by the caveat above, namely that the adjacencies for a given vertex depend on the previous vertex we visited. This means that in our BFS tree, nodes can have multiple parents.
Obviously a simple BFS search won't be sufficient to solve this problem. I know there are algorithms that exist to detect cycles in a graph. One approach might be to detect all the cycles, then for each cycle, detect whether the path is valid. (i.e., does not reverse direction)
Does anyone else have any insights on approaches to solving this problem?
UPDATE:
I followed the approach suggested by #Karussell in the comments.
Here is my solution on github.
The trick was to model the situation using an edge-based graph, not a traditional vertex-based graph. The input file supplied in the contest is conveniently specified in terms of edges already, so this file can be easily used to build an edge-based graph.
The program uses two important classes: Road and Solver. A Road has two integer fields, j1 and j2. j1 represents the source junction and j2 represents the target junction. Each road is one-way, meaning that you can only travel from j1 to j2. Each Road also includes a LinkedList of adjacent Roads and a parent Road. The Road class also includes static methods to convert between the Strings used in the input file and integer indexes representing the A, B, and C points at each junction.
For each entry in the input file, we add two Roads to a HashMap, one Road for each direction between the two junctions. We now have a list of all of the Roads that run between junctions. We just need to connect the roads together at the junctions through the A, B and C switches. If a Road ends at Junction.A, we look up the roads that begin at Junction.B and Junction.C and add these roads as adjacencies. The buildGraph() function returns the Road whose target junction (j2) is "1A" == index 0.
At this point, our graph is constructed. To find the shortest path I simply used a BFS to traverse the graph. We leave the root unmarked and begin by queueing the root's adjacencies. If we find a road whose target junction is "1A" (index 0) then we have found the shortest cycle through the starting point. Once we reconstruct the path using each Road's parent property, it's a trivial matter to set the switches appropriately as required in the problem.
Thanks to Karussell for suggesting this approach. If you want to put your comment in answer form with a short explanation, I will accept it. Thanks to #Origin, as well. I must admit that I did not fully follow the logic of your answer, but that is certainly not to say that it is not correct. If anyone solves this problem using your solution, I would be very interested to see it.
As my comment suggested: I think that you can solve this via edge based graph or via an improvement which is more or less an 'enhanced' node based graph.
Details:
Your situation is similar to turn restrictions in road networks. Those can be modeled if you create one node per (directed!) street and connect that nodes depending on the allowed turns.
So, do not only store the position of your current position but also the direction and possible further 'situations'. To make it possible that even the same position with a 180° turn is different to your current state.
Instead of modeling your 'state' (which is directed!) into the graph you could also assign possible outcomes to every junction - now the algorithm needs to be more clever and needs to decide per junction what to do depending on your earlier state (including direction). I think, this is the main idea of the 'enhanced' node based graph which should be less memory intensive (not that important in your case).
One possible approach: first constract some kind of graph to model all connections (graph G). Then construct another graph in which we will find the cycle (graph H). For each node A in G, we will add a node to graph H. Each A node also has 2 outgoing edges (to the B and C nodes in graph G). In H, these edges will go to the next A node that would be encountered in G. For example, the A node in H corresponding to the A node of the switch with ID 3 would have an outgoing edge to node 9 and node 6 in H. The weight of each edge is the number of switches passed on that route (including the starting switch).
This will yield a graph in which we can grow a forward shortest path tree. If we would reach the start again, the cycle would be complete.
The key is that a switch is only a decision point if it is traversed in the A-> direction. It is not necessary to model the backward direction as this would only complicate the search.
edit: some more clarification
The problem consists of determining the shortest path from A to A (again). The definition of shortest is here the number of switches passed. This will be used in a Dijkstra based search algorithm. We basically are going to do Dijkstra on a graph H in which the cost of the edges is equal to the number of switches in that edge.
In the H graph, we will have a node for each switch. Each node will have 2 outgoing edges, corresponding to the 2 paths one can take (B and C directions). The edges in H will correspond to an entire route between 2 A nodes in the original graph. For the example in the problem description, we get the following:
A node corresponding to switch 1:
1 outgoing link to node 2, weight 2, corresponding to taking the C
direction when leaving switch 1. The weight is 2 because we pass switch 1 and switch 3 if we go from A1->C1->C3->A3->A2
1 outgoing link to node 3, weight 2, corresponding to taking the B direction
A node corresponding to switch 2:
1 outgoing link to node 6, weight 2, corresponding to taking the B direction
no second link as the C direction is a dead end
A node corresponding to switch 3:
1 outgoing link to node 6, weight 2, corresponding to taking the C direction
1 outgoing link to node 9, weight 3, corresponding to taking the B direction and passing switches 3, 7 and 8
and so on for every switch. This yield a graph with 10 nodes, each having at most 2 directed edges.
Now we can start building our Dijkstra tree. We start at node 1 and have 2 possible directions, B and C. We put those on a priorityqueue. The queue then contains [node 2,weight 2] and [node 3, weight 2] as we can reach the A entrance of switch 2 after passing 2 switches and the A entrance of switch 3 after passing 2 switches. We then continue the search by taking the lowest weight entry from the queue:
[node 2, weight 2]: only the B direction to take, so put [node 6, weight 4] on the queue
[node 3, weight 2]: 2 directions to take, so add [node 6, weight 4] and [node 9, weight 5] to the queue.
[node 6, weight 4]: 2 directions possible, add [node 4, weight 5] and [node 8, weight 8] to the queue]
[node 9, weight 5]: only the C direction, add [node 10, weight 6]
[node 4, weight 5]: add [node 5, weight 7] for the C direction and [node 1, weight 9] for the B direction]
[node 10, weight 6]:add [node 1, weight 8] for the C direction and [node 1, weight 10] for the B direction
[node 5, weight 7]:add [node 1, weight 11] and [node 8, weight 10]
[node 8, weight 8]: add [node 7, weight 9]
[node 1, weight 8]: we found our way back so we can stop
(mistakes are possible, I'm just doing this by hand)
The algorithm then stops with a final length of 8 for a cycle. Determining the followed path is then just a matter of maintaining parent pointers for the nodes when you settle them and unpack the path.
We can use Dijkstra because each node in H corresponds to traversing an original node (in G) in the right direction. Each node in H can then be settled in a Dijkstra fashion so the complexity of the algorithm is limited to that of Dijkstra (which can handle the 100k upper limit for the number of switches).
Related
Consider a Graph connecting various cities through railways. Every Node is a city which has various railway lines (edges) to reach the other city. You need to find if a meeting point exists i.e. one such route (i.e. sequence of lines) which when taken always arrives to the same city no matter from which city you start.
Eg.
Consider Graph G = [[2, 1], [2, 0], [3, 1], [1, 0]]. The k^th element of Graph (counting from 0) will give the list of stations directly reachable from station k.
The outgoing lines are numbered 0, 1, 2... The r^th element of the list for station k, gives the number of the station directly reachable by taking line r from station k.
Then one could take the path [1, 0]. That is, from the starting station, take the second direction, then the first. If the first direction was the red line, and the second was the green line, you could phrase this as:
if you are lost, take the green line for 1 stop, then the red line for 1 stop.
So, consider following the directions starting at each
0 -> 1 -> 2.
1 -> 0 -> 2.
2 -> 1 -> 2.
3 -> 0 -> 2.
So, no matter the starting station, the path leads to station 2.
The limits for lines is from 0 to 5 and the limits for station is 2 to 50. So in the worst case there might be 2^(49*5) subsets of routes so brute force is out of the question.
Edit1 :
After mcdowella mentioned this problem being called Synchronising sequences in DFAs
Ans also, I am interested only if a meeting path exists or not I found out this pdf (slide 5) states that
Adler and Weiss, 1970 (Conjecture)
Every finite strongly connected aperiodic directed graph of uniform outdegree has
a synchronizing coloring.
Alternatively,
Every strongly connected graph with 'x' cycles all having gcd 1 (which states
aperiodicity) has a meeting path.
Which works for most cases. However, it's not hard to come up with something like this :
Which is neither strongly connected, so aperiodicity becomes out of question. And still has a meeting path [0 -> 1]. So what am I missing here?
You don't say what to do if the path says to go out along x and there is no outgoing link labelled x, so I am going to suppose that all nodes have a full set of outgoing links, or we treat such missing links as links back to the current node, or copies of the link labelled 0, or something.
I start with a set of possible nodes that we may be on, initialised to the set of all nodes.
For each label, take the set of possible nodes and compute the set of nodes that you get by going from any node in the current set, following the current label, to another node. If, for each possible label, the result is always the same set as the current set of possible nodes, give up. This means that each label maps each node in the current set to a different node, and, given any node in the current set and any path, of whatever length, you can find a unique node in the current set with a path that ends in the chosen node, so the situation looks hopeless to me.
If, for some label, the set of nodes after applying this label to the current set is smaller than the current set, note down that label, make the new smaller set the current set, and repeat.
If this process terminates in a set of size one you have worked out a path that ends with that node a meeting point, and the path is no longer than the number of nodes in the original graph, since each step reduces the number of nodes in the graph by at least one. Each step costs you at most the number of edges in the graph, so for a graph with N nodes and K labels per node, the cost is at most KN^2.
In fact, since the check at each stage amounts to looking for at least one node in the current set with two incoming edges with the same label on it, and then removing all nodes in the current set which don't have an incoming edge with the chosen label, I would hope that you can make the cost at each step linear in the number of nodes discarded, and argue that the total cost is something below O(KN^2)
(I'm pretty sure that I have seen this worked out properly somewhere as an exercise in robot navigation or something so a web search might be more reliable than reading this, but I've had fun writing it, and it looks plausible to me).
Edit -
It appears that the problem is referred to as a search for synchronizing sequences for finite automata. math.uni.wroc.pl/~kisiel/auto/Homing.pdf looks very promising but I haven't gone through it in detail.
TL;DR: There is an O(n^2) algorithm which determines if a meeting path exists, which is described here:
Consider P(G), the power graph of the original graph G. The power graph is created by taking all subsets of the set of nodes of the original graph G, and making each of those subsets into nodes themselves. The edges connect nodes as follows:
(using G = [[2, 1], [2, 0], [3, 1], [1, 0]]), and looking at the edge 1 (or line 1, as your problem states)
{0, 1, 2} -> {1, 0, 1} = {0, 1}, since, when taking line 1, 0 -> 1, 2 -> 1, 1 -> 0.
{0, 3} -> {1, 0}, since, when taking line 1, 0 -> 1 and 3 -> 0.
etc.
Now, if there are n stations, then, if there exists a path from the node {0, 1, ..., n-1} in P(G) to a singleton (set of one element) node in P(G), there is a meeting point. Because, if you take that path as the series of lines, starting at any of the stations will end in the same station. Now, creating the powerset is of course very expensive (O(2^n)), but making an important remark causes the amount of computation to be O(n^2).
This remark is very similar to that of (Černý, 1964) on the word synchronization problem of DFA's. A proof sketch of this remark is at the end this answer. The remark is that, when looking at the power graph of G:
Every node representing a subset of size 2 has a path to a singleton node if and only if there exists a meeting path
That is, when we create P(G), we only need to create nodes that represent subsets of size 2 or less. This means that P(G) will have only n^2 nodes.
So, essentially the algorithm is:
Create P_2(G), the power graph of G where each node represents a subset of size 2 or less.
For each node representing a subset of size 2 in P_2(G):
If there is no path from this node to a singleton node, return False
return True (will only happen if, for every node representing a subset of size 2, there is a path to a singleton node).
Part 2 of the algorithm can be done with DFS: you can reverse all of the edges of P_2(G) and begin the DFS stack with all of the singleton nodes. Then, if the DFS tree contains all of the nodes representing subsets of size 2, then all of the nodes representing subsets of size 2 have a path to a singleton node.
Part 1 is O(n^2) and Part 2 can be done in O(n^2) by reversing the edges of the graph and performing DFS as described above.
I hope this has been mostly clear.
Proof of the remark:
We first treat the direction where, a meeting path exists implies that, for every node representing a subset of size 2, there is a path to a singleton node. Just take the meeting path. Since it's a meeting path, starting at any node in G ends up in the same node. So, taking the meeting path will reach a singleton node.
Now, if for every node representing a subset of size 2, there is a path to a singleton node: then, one can construct a meeting path. Take two different nodes representing subsets of size 2, name them A and B. Then, take A's path to a singleton. Taking this path, A -> {i} and B -> C, For some C and {i}. Then, take C's path to a singleton. {i} -> {j} and C -> {k}. Then, there is a meeting path for the node representing {j, k}. So, we can find a meeting path for the union of A and B. Thus, we can do this for any pair of nodes. Inductively, you can find a meeting path for the union of any set of nodes representing subsets of size 2, so this can be done until the entire set of nodes is the starting point and a singleton node is the end.
As I already wrote in a comment on mcdowella's comment, I suspect this problem to be NP-complete. But a reasonable heuristic may allow you to get to the target in a reasonable time.
The following idea is based on A*. You represent the current set of stations as nodes (i.e. every set corresponds to one node). Since you have at most 50 stations, every step can be represented as a 64-bit number (where each number describes if the according station is in the set).
You want to maintain a list O of open nodes and a list V visited nodes. Start with C and O containing a single node that represents all stations.
The algorithm then has the following structure:
Choose the node in O with the least number of stations -> n.
Remove n from O.
For every line
transform n to the set of stations nt that result from travelling from the stations in n with the specified line (and count the number of stations to speed things up).
If nt has a single station, you have found a meeting point (there may be more than one)
If nt has not been visited before, add it to O and V and set its path to the current path.
If nt has already been visited, you have two choices. Either update the path of nt to achieve a path of minimal length or just ignore it.
Go to 1
The size of this graph is exponential in the length of the path. Therefore, this algorithm has exponential worst-case time and space complexity. However, since you always pick the node with the fewest stations, you take a step that is assumed to take you to the target on the fastest route. This may be a wrong step, which is why we need to keep the remaining graph. You will also calculate the graph on the fly, which avoids keeping the entire graph in memory (unless there is no solution).
I need help in understanding how to solve the following problem:
Professor Adam has two children who, unfortunately, dislike each other. The problem is so severe that not only do they refuse to walk to school together, but in fact each one refuses to walk on any block that the other child has stepped on that day. The children have no problem with their paths crossing at a corner. Fortunately both the professor's house and the school are on corners, but beyond that the professor is not sure if it is going to be possible to send both of the children to the same school. The professor has a map of the town. Show how to formulate the problem of determining whether both the children can go to the same school as a maximum-flow problem.
The only thing I can think of is to have a four corner graph. The upper left-hand vertex represents the source (Adam's house) and the lower right-hand corner represents the sink (school). The corner x on the upper right-hand corner represents a corner in the neighborhood while y represents the lower left-hand corner of the neighborhood. Thus, we have paths going from S -> C1, S -> C2, C1 -> t, and C2 -> t. Each path has a weight of 1 since it can only accommodate one child. The max flow of this graph is 2 which proves that they can attend the same school.
The problem I am having is that I am not sure if this solution that I've arrived upon satisfies the problem. The part that is stumping me the most is that I am not sure what this means: but in fact each one refuses to walk on any block that the other child has stepped on that day. How can this statement make sense if both live in the same house on the same block?
UPDATE: turned out, I misread the problem. The problem asks to find "edge-disjoint" paths, not vertex-disjoint paths. In this case the solution is just to represent each corner as a vertex, each block as an edge with capacity one, and run regular max flow (as correctly suggested by Curious below).
I believe that that OP has the same confusion based on
but in fact each one refuses to walk on any block that the other child has stepped on that day. How can this statement make sense if both live in the same house on the same block?
Note that children live in the same house on the same corner, not on the same block.
I leave the rest of the answer in case someone one day is actually looking for the vertex disjoint problem:
If I understand the problem correctly, what it asks is to find two vertex-disjoint paths from source to sink. Just using graph as is, and assigning capacity of 1 to each edge is not enough. Consider the following example:
s -> C1, C1 -> C3, C3 -> C4, C4 -> t
s -> C2, C2 -> C3, C3 -> C5, C5 -> t
If you assign capacity of 1 to each of these edges, and run any max flow algorithm, it will find a max flow of 2, but there's no two vertex-disjoint paths (both paths would go through vertex C3).
To address it, you need to adjust your graph. For each vertex except s and t, split it in two. Say vertex u was split into u' and u''. Make all the edges that were going into u go into u', and all the edges that were going from u go from u'' (the capacity of those edges does not matter, as long as it is positive, so you can set it to 1). Finally, add an edge from u' to u'' with capacity 1, and run max flow on this graph. Because of those edges we added between split nodes, each vertex will be used at most once, because for the vertex to be used we need to enter u', go from u' to u'' and exit from there, and only one unit of flow can go from u' to u''.
Lets keep it simple ..
First things First.Why did you restrict only to 2 corners other than his house and school . It was not mentioned that way in the problem .
Modelling of Adam's Problem could go like this
Vertices : all corners of town
Directed edges : all roads connecting the corners in both directions i.e if we have 2 corners p,q then we would have edge from p to q as well as from q to p
for all edges (u,v) , c(u,v)=1
Now solve the max flow problem and if it is >= 2 , Adam is lucky .
I've never heard of a max-flow problem, so this is what I gather from wikipedia.
It seems like the graph (V,E) should have one vertex for each intersection of streets and one edge for each street (between intersections). Then each edge would have capacity 1 (as you say). Of course, if one of the children makes it to the school, they can also make it back home (using the analogous path in the "opposite graph" where all the edges are reversed).
Then the only ambiguity is: what should the direct of an edge be? If the graph does not have to be directed, this could work as the formulation of the problem.
Wikipedia
Since the question specifies that the house (s) and school (t) both are on corners, I assume that corners don't count as "walking on a block" and the question says they have no problems crossing paths at a corner, so for instance they could both cross the street to another block together, as long as only one of them took the sidewalk to another corner and the other immediately crossed the street to another block.
In that case, the limiting factor in the flow is blocks, so they must become edges in the flow diagram with capacity of 1. But what do they connect? They have to connect to other blocks. So imagine a square of 9 blocks:
1 2 3
4 5 6
7 8 9
With the house at the southeast corner of 1 and the school at the southeast corner of 5. Both children could cross the street to block 5, but only one can walk around block 5 to get to the school at the opposite corner. The other one might as well cross to block 4, then to 7, then to 8 where he can cross the street to the school on the corner of block 5.
So the house (s) can get to blocks 1, 2, 4, and 5. The school can be gotten to from 5, 6, 8 or 9. My first thought is to model each block as two nodes, input and output, and an edge with a capacity of 1 connecting the input to the output. Other nodes will be linked with edges that have a capacity of at least 2. You also need nodes for s and t. Link s to the inputs of 1, 2, 4, and 5 and the outputs of 5, 6, 8, 9 go to t. Then link the block outputs up to the inputs of any block you can get to from a corner, i.e. output of 1 goes to inputs of 2, 4, 5 and outputs of 2, 4, 5 goes to the input of 1 as well.
A simpler way to think of it might be that each corner is a node connected to the inputs of the blocks around it and the outputs of the blocks around it connected into the corner node. All edges should have a capacity of at least two though, except the ones connecting block inputs and outputs which have a capacity of 1. That way the limiting factor is "walking on a block". As long as the flow is 2 at the end, they can make it.
So let's simplify the diagram and get rid of the blocks we won't be using. One child can walk around block 5 from s to t, the other can cross the street to 4, then cross to block 8 at corner a and walk along block 8 to corner t where the school is:
s
4 5
a t
8
Here are the edges:
s->4in (capacity 2)
s->5in (capacity 2)
4in->4out (capacity 1) // limiter
5in->5out (capacity 1) // limiter
8in->8out (capacity 1) // limiter
4out->s (capacity 2)
4out->a (capacity 2)
5out->s (capacity 2)
5out->a (capacity 2)
5out->t (capacity 2)
8out->a (capacity 2)
8out->t (capacity 2)
a->4in (capacity 2)
a->5in (capacity 2)
a->8in (capacity 2)
One child's path s->5in->5out->t
Other child's path s->4in->4out->a->8in->8out->t
I was also looking for solution and found this and it does appear correct to me.
http://www.repond.ch/ressources/cse/algorithme/week10/exercise7-sol.pdf?PHPSESSID=col0hua0ehpk57givsva99mco4
"Let us model the city map with a graph G(V,E) in the following way: V contains each corner in the town and E contains the roads. More specifically, we assume there is an edge between two nodes u,v belongs to V
if there is a road connecting the corners u and v in the city. We assume each edge has a capacity of 1. Furthermore, let the house of Professor Adam be
the source, s, and the school be the sink, t. Now we can formulate the problem as a max-flow problem: the flow on edge (u, v) will represent if any of the children has stepped on the road connecting the corners u and v. Furthermore, we let only integral flows so f(u, v) = 1 in this case. Therefore, since the capacity of each edge in the graph is c(u, v)= 1, if a flow is passing over one link, that link can not be used anymore. which means the other kid will not take that road to go to school. Now if both of the kids can go to school, it means that there is flow from the source (house) to the sink (school) with value at least 2. Likewise if one could find a maximal
integral flow in G from s to t that has a value of at least 2, then both children can go to school. Otherwise, it won’t be possible."
Suppose that we are given a directed graph H = (V, E). For each edge e, the weight of the edge, w(e) is either 2, 3 or 5. Modify the BFS so that it will compute the length of the shortest path from a single source vertex s. Explain why your algorithm is correct and determine its worst-case running time (You may assume that H is represented via an adjacency list).
How would you go about this? What makes the specific weight edges different from just any?
You can consider imaginary nodes between the edges. So if between 2 nodes there is an edge of length 2. You make an intermediary node and add edges of length 1 between them. Then use the normal breadth first search. (You also need to do this for nodes of length 3 and 5, adding 2 and 4 nodes). Since you only add a O(E) nodes it's the same complexity.
I am reading the application of BFS algorithm. One of the application which i read is to check weather a give graph is bipartite graph or not.Now I want to know, is there any algorithm to convert a graph into bipartite set/graph.
For example we have give a set of edges as
E={ (4, 1),( 1 ,2), (2 ,3),( 7, 2),( 1 ,5),( 8 ,4), (5 ,8),( 8, 9)}
and set of vertices
V= { 1,2,3,4,5,6,7,8}
we have to create bipartite set/graph.
Expected output as :-
s1={1 ,4, 8, 1 ,7 ,3}
s2={2, 5, 6, 9}
The general BFS algorithm to check if a graph is bipartite is:
Start from a vertex v_0, and label it s1.
Mark all v_0's neighbours as s2, and queue them.
Mark all the neighbour's neigbours as s1, and queue them
If, at any point, you get to mark as s2 a vertex already marked as s1 or vice versa, the graph is not bipartite. If, instead, you end up with an empty queue, you are done, and you have your partition.
EDIT
If what you want to know, instead, is how you can build a bipartite graph from a general one, you should first add a metric to compare two different solutions : otherwise, removing all the edges and assigning randomly the vertices to two groups, will always generate a ( trivial ) bipartite graph from any given one.
The edge bipartization problem, that is, deleting the minimum number of edges to make a graph bipartite, is NP-hard. Here are slides of a talk about how to solve it as efficiently as possible.
I'm trying to generate an undirected graph in which each node has a maximum degree associated with it. That is, if a node has a maximum degree of 2, it can connect to at most two nodes (connected node would be allowed, but not 0). My problem is that I'm trying to generate a graph in which its possible to get from one node to the other. Currently, I can have nodes "randomly" connect to one other, but the problem is that its possible to create divided graphs, ie if you have 10 nodes, then sometimes inadvertently two graphs of 5 nodes each forms. If anyone knows of an efficient solution, I'd love to hear it!
EDIT: Suppose that I have a graph with ten nodes, and I specify a maximum degree of 2. In this case, here is something that would be desirable:
Whereas this is what I'm trying to avoid:
Both graphs have a maximum degree of 2 per node, but in the second image, it's not possible to select an arbitrary node and be able to get to any other arbitrary node.
This problem is a pretty well-known problem in graph theory, soluble in polynomial time, the name of which I forget (which is probably "find a graph given its degree sequence"). Anyhow, Király's solution is a nice way to do it, explained much better here than by me. This algorithm solves for the exact graphs that satisfy the given degree sequence, but it should be easy to modify for your more loose constraints.
The obvious solution would be to build it as an N-way tree -- if the maximum degree is two, you end up with a binary tree.
To make it undirected, you'll have pointers not only to the "child" nodes, but also a backward pointer to the "parent" node. At least presumably, that one doesn't count toward the degree of the node (if it does, your degree of two basically ends up as a doubly-linked linear list instead of a tree).
Edit: post-clarification, it appears that the latter really is the case. Although they're drawn different (with links going in various different directions) your first picture showing the desired result is topologically just a linear linked list. As noted above, since you want an undirected graph, it ends up as a doubly linked list.
It sounds like you already know what the graph should look like, so I believe if you can use a depth-first search approach. Although breath-first search can be used to avoid recursion.
For example, if you have the nodes 1-5, and k=2, then you can build a graph by starting at node 1, and then simply randomly choosing an unvisited node. Like so:
1 [Start at 1]
1-2 [expand 2, add edge(1,2) to graph]
1-2-3 [expand 3, add edge(2,3) to graph]
1-2-3-4 [expand 4, add edge(3,4) to graph]
1-2-3-4-5 [expand 5, add edge(4,5) to graph]
1-2-3-4-5-1 [expand 1, add edge(5,1) to graph] (this step may or may not be done)
If an edge is never used twice, then p paths will lead to degree p*2 overall, with the degree of the start and end nodes dependent on if the paths are really a tour. To avoid duplicate work, it is probably easier to just label of the vertices as the integers 1 through N, then create edges such that each vertex, v, connects to the vertex numbered (v+j) mod (N+1) where j and (N+1) are co-prime < N-1. The last bit making things a bit problematic, as the number of co-primes from 1 to N can be limited if N is not prime. This means solutions don't exist for certain values, at least in the form of a new Hamiltonian path/tour. However, if you ignore the co-prime aspect and simply make j be integers from 1 thru p, then go through each vertex and create the edges (instead of using the path approach), you can make all the vertices have degree k, where k is an even number >= 2. This is achievable in O(N*k), although it may be pushed back as far as O(N^2) if co-prime method is used.
Thus the path for k=4 would look like this, if started at 1, with j=2:
1 [Start at 1]
1-3 [expand 3, add edge(1,3) to graph]
1-3-5 [expand 5, add edge(3,5) to graph]
1-3-5-2 [expand 2, add edge(5,2) to graph]
1-3-5-2-4 [expand 4, add edge(2,4) to graph]
1-3-5-2-4-1 [expand 1, add edge(4,1) to graph] (this step may or may not be done)
Since |V| = 5 and k = 4, the resulting edges form a complete graph, which is expected. It's also works out since 2 and 5 are co-prime.
Obtaining an odd degree is a bit more difficult. First obtain the degree k-1, then edges are added in such a way an odd degree is obtained overall. It seems fairly easy to get very close (with one or two exceptions) to all edges being an odd degree, but it seems impossible or at least very difficult with odd number of vertices, and requires a careful selection of edges with even number of vertices. The section of which, isn't easy to put into an algorithm. However, it can be approximated by simply picking two unused vertices and creating an edge between them such that the vertices are not used twice, and the edges are not used twice.