Enumerating Cyclic Orientations of a Graph

Enumerating Cyclic Orientations of a Graph

Alessio Conte Università di Pisa, conte,grossi,marino@di.unipi.it    Roberto Grossi Università di Pisa, conte,grossi,marino@di.unipi.it    Andrea Marino Università di Pisa, conte,grossi,marino@di.unipi.it    Romeo Rizzi Università di Verona, rizzi@di.univr.it

Acyclic and cyclic orientations of an undirected graph have been widely studied for their importance: an orientation is acyclic if it assigns a direction to each edge so as to obtain a directed acyclic graph (DAG) with the same vertex set; it is cyclic otherwise. As far as we know, only the enumeration of acyclic orientations has been addressed in the literature. In this paper, we pose the problem of efficiently enumerating all the cyclic orientations of an undirected connected graph with vertices and edges, observing that it cannot be solved using algorithmic techniques previously employed for enumerating acyclic orientations. We show that the problem is of independent interest from both combinatorial and algorithmic points of view, and that each cyclic orientation can be listed with delay time. Space usage is with an additional setup cost of time before the enumeration begins, or with a setup cost of time.

1 Introduction

Given an undirected graph with vertices and edges, an orientation transforms into a directed graph by assigning a direction to each edge. That is, an orientation of is the directed graph such that the vertex set is the same as , and the edge set is an orientation of : exactly one direction between and holds for any undirected edge . An orientation is acyclic when does not contain any directed cycles, so is a directed acyclic graph (DAG); otherwise we say that the orientation is cyclic.

Acyclic orientations of undirected graphs have been studied in depth. Many results concern the number of such orientations: Stanley [14] shows how, given a graph and its chromatic number , the number of acyclic orientations of can be computed by using the chromatic polynomial (a special case of Tutte’s polynomial). Other results rely on the so called acyclic orientation game: Alon et al. [1] inquire about the number of edges that have to be examined in order to identify an acyclic orientation of a random graph ; Pikhurko [10] gives an upper bound on this number of edges in general graphs. The counting problem is known to be #P-complete [8] and enumeration algorithms that list all the acyclic orientations of a graph are given in [2] and [13].

We consider cyclic orientations, which have been also studied from many points of view. Counting them is co-#P-complete [8]. In Fisher et al. [5], given a graph G and an acyclic orientation of it, the number of dependent edges, i.e. edges generating a cycle if reversed, has been studied. This number of edges implicitly gives a hint on the number of cyclic orientations in a graph. In [11] an algorithm has been given to make inference about causal structure in cyclic graphs. In [12] directed cyclic graphs are used to model economic processes, and an algorithm is given to characterize conditional independence constraints of these processes.

In this paper we address the problem of enumerating all the cyclic orientations of a graph.

Problem 1

Enumerating the set of all the directed graphs that are cyclic orientations of an undirected graph .

We analyze the cost of an enumeration algorithm for Problem 1 in terms of its setup cost, meant as the initialization time before the algorithm is able to lists the solutions, and its delay cost, which is the worst-case time between any two consecutively enumerated solutions (e.g. [7]). We are interested in algorithms with guaranteed delay, where the notation ignores polylogs.

A naive solution to Problem 1 uses the fact that enumeration algorithms exist for listing acyclic orientations [2, 13]. It enumerates the cyclic orientations by difference, namely, by enumerating all the possible edge orientations and removing the acyclic ones. However, this solution does not guarantee any polynomial delay, as the number if cyclic orientations can be much larger or much smaller than the number of acyclic ones. For example, a tree with edges has and . On the other extreme of the situation, we have cliques. An oriented clique is also called a tournament, and a transitive tournament is a tournament with no cycles. A clique of nodes (and edges) can generate different tournaments, out of which exactly will be transitive tournaments [9]. As grows faster than , we have that the ratio tends to 0 for increasing , where .

To the best of our knowledge, an enumeration algorithm for Problem 1 with guaranteed delay is still missing. We provide such an algorithm in this paper, namely, listing each cyclic orientation with delay time. Space usage is memory cells with a setup cost of time, or memory cells with a setup cost of time. Interestingly, Problem 1 reveals to be a rich source for enumerations techniques, and our solution offers new combinatorial and algorithmic techniques when compared to previous work on the enumeration of acyclic orientations [2, 13].

In the following, for the sake of clarity, we will call edges the elements of (undirected graph) and arcs the elements of (directed graph). We will assume that the graph in input is connected and we will denote as and respectively its number of nodes and edges.

The paper is organized as follows. Section 2 gives an overview of our enumeration algorithm. Section 3 describes the initialization steps, and shows how to reduce the problem from the input graph to a suitable multi-graph that guarantees to have a chordless cycle (hole) of logarithmic size. The latter is crucial to obtain the claimed delay. Section 4 shows how to enumerate in the multigraph and obtain the cyclic orientations for the input graph. Section 5 describes how to absorb the setup cost using more space. Finally, some conclusions are drawn in Section 6.

2 Algorithm overview

The intuition behind our algorithm for an undirected connected graph is the following one. Suppose that is cyclic, otherwise there are no cyclic orientations. Consider one cycle111This will actually be a chordless cycle of logarithmic size (called log-hole). in : we can orient its edges in two ways so that the resulting is a directed cycle. At this point, any orientation of the remaining edges, e.g. those in , will give a cyclic orientation of . Thus, the interesting cases are when the resulting is not a directed cycle.

The idea is first to generate all possible orientations of the edges in , and then assign some suitable orientations to the edges in . This guarantees that we have at least two solutions for each orientation of , namely, setting the orientation of so that is one of the two possible directed cycles. Yet this is not enough as we could have a cyclic orientation even if is not a directed cycle.

Therefore we must consider some cases. One easy case is that the orientation of already produces a directed cycle: any orientation of will give a cyclic orientation of . Another easy case, as seen above, is for the two orientations of such that is a directed cycle: any orientation of will give a cyclic orientation of . It remains the case when the orientations of both and are individually acyclic: when put together, we might have or not a directed cycle in the resulting orientation of . To deal with the latter case, we need to “massage” and transform it into a multigraph as follows. We refer the reader to Algorithm 1.

Algorithm setup is performed as described in Section 3. We preprocess with dead-ends removal and edge chain compression. The result is an undirected connected multigraph , where the edges are labeled as simple and chain. After that we find a chordless cycle of logarithmic size in , and remove from , obtaining the labeled multigraph , where .

Enumerating cyclic orientations described in Section 4 exploits the property (which we will show later) that finding cyclic orientations of corresponds to finding particular orientations in , called extended cyclic orientations, and of , called legal orientations. In the for loop, these orientations of and are enumerated so as to find all the cyclic orientations of . As we will see for the latter task, it is important to have of logarithmic size to guarantee our claimed delay.

Input: An undirected connected graph
Output: All the cyclic orientations
Algorithm setup (Section 3):
Remove dead-ends (nodes of degree ) recursively from
replace ’s maximal paths of degree-2 nodes with chain edges
a log-hole of
delete the edges of from , i.e.
[2mm] Enumerate cyclic orientations (Section 4):
for each extended orientation of multigraph do
       for each legal orientation of log-hole (see Algorithm 2) do
             combine and , where
             Output each of the cyclic orientations of corresponding to
Algorithm 1 Returning all the cyclic orientations of

3 Algorithm Setup

3.1 Reducing the problem to extended cyclic orientations

In the following we show how to reduce Problem 1 to an extended version that allows us to neglect dead-ends and chains.

Dead-end removal.

Given an undirected graph , a dead-end is a node of degree 1. We recursively remove all dead-ends, so that all the surviving nodes have degree 2 or greater. By removing these nodes and computing the cyclic orientations in the cleaned graph, we can still generate solutions for the original graph by using both orientations of the unique incident edge to each dead-end, as emphasized by the following lemma, whose proof is straightforward.

Lemma 1

Let be a graph, a dead-end and its unique incident edge. Let be the graph without and the edge . The set of all the cyclic orientations of is composed by the orientations and , for all the cyclic orientations of .

The dead-end removal can be done by performing a DFS recursive traversal of , starting from an arbitrary node . Every time a node of degree 1 is visited, it is removed from the graph. When the recursion ends in a node, the latter is removed if all of its neighbors have been removed except one (which is its parent in the DFS tree). Finally, when the traversal ends, it might be that the node from which we started has degree 1. To complete the process, if has now degree 1, we remove it from the graph. The DFS of and the removal of its dead-ends can be done in .

The rationale for removing dead-ends is to have shorter cycles: for example, consider a “necklace” graph with nodes, for even, such that nodes form a cycle, and the remaining nodes have degree 1 and are attached to one of the nodes in the cycle, such that each node in the cycle has degree 3 and is connected to one node of degree 1. With the removal of dead-ends, the cycle has only nodes of degree 2 and can be compressed as discussed in the next paragraph.

Chain compression.

It consists in finding all the maximal paths where has degree 2 (with ), and replacing each of them, called chain, with just one edge, called chain edge. It is easy to see that this task can be accomplished in time by traversing the graph in a DFS fashion from a node of degree . The output is an undirected connected multigraph , where are the nodes of whose degree is , and are the chain edges plus all the edges in which are not part of a chain.222The degenerate case of with nodes can be handled separately. The latter ones are called simple edges to distinguish them from the chain edges. In the rest of the paper, will be seen as a multigraph where and each of the edges has a label in {simple, chain}, since it might contain parallel edges or loops. For this, we define the concept of extended orientation as follows.

Definition 1 (Extended Orientation)

For a multigraph having self loops and edges labeled as simple and chain, an extended orientation is an orientation of its edge set : for any simple edge , exactly one direction between and holds; for any chain edge , either is broken, or exactly one direction between and holds. A directed cycle in cannot contain a broken edge.

Broken edges correspond to chain edges that, when expanded as edges of , do not have an orientation as a directed path. This means that they cannot be traversed in either direction. Note that this situation cannot happen for simple edges. The following lemma holds.

Lemma 2

If we have an algorithm that list all the extended cyclic orientations of with delay , for some , then we have an algorithm that lists all the acyclic orientations of the graph with delay .


For each extended cyclic orientations we return a set of cyclic orientations of : any edge of maintains the same direction specified by in all the solutions in ; for each chain of , we consider the edges corresponding to in , say : if has a direction in , the same direction of is assigned to all the edges in all the solutions in ; if has no direction assigned, i.e. broken, we have to consider all the possible ways of making the path broken (these are all the possible ways of directing the edges except the only two directing a path). All the solutions in differ for the way they replace the chain edges.

Getting extended cyclic orientations in delay, iterating over all the chain edges , and iterating over all the corresponding edges of assigning the specified directions as explained above, we return acyclic orientations of the graph with delay .∎

Lemma 2 allows us to concentrate on extended cyclic orientations of the labeled multigraph rather than on cyclic orientations of . Conceptually, we have to assign binary values (the orientation) to simple edges and ternary values (the orientation or broken) to chain edges. If we complicate the problem on one side by introducing these multigraphs with chain edges, we have a relevant benefit on the other side, as shown next.

3.2 Logarithmically bounded hole

Given the labeled multigraph obtained in Section 3.1, namely , we perform the following two steps.

  1. Finding a log-hole. Find a logarithmically bounded hole (hereafter, log-hole) in : it is a chordless cycle whose length is either the girth of the graph (i.e. the length of its shortest cycle) or this length plus one.333Minimum cycle means the cycle having minimum number of edges (i.e. a self loop), where chain edges count just one like normal edges.

  2. Removing the log-hole. Remove the edges in from , obtaining , where .

3.2.1 Properties of the log-hole.

Since is a multigraph with self-loops, a log-hole of can potentially be a self-loop. In any case, the following well-known result holds.

Lemma 3 (Logarithmic girth [3, 4])

Let be a graph in which every node has degree at least . The girth of is .

Lemma 3 means that the log-hole of has length at most , thus motivating our terminology.

The log-hole can be found by finding the girth, that is performing a BFS on each node of the multigraph to identify the shortest cycle that contains that node, in time . By applying the algorithm in [6], which easily extends to multigraphs, we compute in time : in this case, if chords are present in the found , in time we can check whether includes a smaller cycle and redefine accordingly.

4 Enumerating cyclic orientations

We now want to list all the cyclic orientations of the input graph . By Lemma 2 this is equivalent to listing the extended cyclic orientations of the corresponding labeled multigraph obtained from by dead-end removal and chain compression. We now show that the latter task can be done by suitably combining some orientations from the labeled multigraph and the log-hole using an algorithm that is organized as follows.

  1. Finding extended orientations. Enumerate all extended orientations (not necessarily cyclic) of the multigraph .

  2. Putting back the log-hole. For each listed , consider all the extended orientations of the log-hole such that contains a directed cycle, and obtain the extended cyclic orientations for the multigraph .

4.0.1 Finding extended orientations.

This is now an easy task. For each edge in that is labeled as simple, both the directions and can be assigned; if is labeled as chain, the directions and , and broken can be assigned. Each combination of these decisions produces an extended orientation of . If there are simple edges and broken edges in , where , this generates all possible extended orientations. Each of them can be easily listed in delay (actually less, but this is not the dominant cost).

4.0.2 Putting back the log-hole.

For each listed we have to decide how to put back the edges of the cycle , namely, how to find the orientations of that create directed cycles.

Definition 2

Given the cycle and , we call legal orientation any extended orientation of such that the resulting multigraph is cyclic, where .

The two following cases are possible.

  1. is cyclic. In this case each edge in can receive any direction, including broken if the edge is a chain edge: each combination of these assignments will produce a legal orientation that will be output.

  2. is acyclic. Since is a cycle, there are at least two legal orientations obtained by orienting as a directed cycle clockwise and counterclockwise. Moreover, adding just an oriented subset of edges to can create a cycle in : in this case, any orientation of the remaining edges of (including broken for chain edges) will clearly produce a legal orientation.

While the first case is immediate, the second case has to efficiently deal with the following problem.

Problem 2

Given acyclic and cycle , enumerate all the legal orientations of .

In order to solve Problem 2, we exploit the properties of . In particular, we compute the reachability matrix among all the nodes in , that is, for each pair of nodes in , is if can reach in the starting , otherwise. We say that is cyclic whether there exists a pair such that . This step can be done by performing a BFS in from each node in : by Lemma 3 we have , and so the cost is time. Deciding the orientation of the edges and the chain edges in is done with a ternary partition of the search space. Namely, for each edge in , if is simple we try the two possible direction assignments, while if it is a chain we also try the broken assignment. In order to avoid dead-end recursive calls, after each assignment we update the reachability matrix and perform the recursive call only if this partial direction assignment will produce at least a solution: both the update of and the dead-end check can be done in (that is, the size of ).

Scheme for legal orientations.

The steps are shown by Algorithm 2. At the beginning the reachability matrix is computed and is passed to the recursive routine LegalOrientations. At each step, is the partial legal orientation to be completed and is the set of broken edges declared so far. Also, is the index of the next edge of the cycle , with (we assume to close the cycle): if then all the edges of have been considered and we output the solution together with the list of broken edges in . Each time the procedure is called we guarantee that the reachability matrix is updated.

Let be the next edge of to be considered: for each possible direction assignment or of this edge, we have to decide whether we will be able to complete the solution considering this assignment. This is done by trying to add the arc to the current solution. If there is already a cycle, clearly we can complete the solution. Otherwise, we perform a reachability check on : it is still possible to create a directed cycle if and only if any two of the nodes in , say and satisfy or . This condition guarantees that a cycle will be created in the next calls, since we know there are edges in between and that can be oriented suitably. Finally, when is a chain, the broken assignment is also considered: does not need to be updated as the broken edge does not change the reachability of .

The reachability and cyclicity checks are done by updating and checking the reachability matrix (and restoring when needed). Updating when adding an arc corresponds to making , and all nodes reachable from , reachable from and nodes that can reach . This can be done by simply performing an or between the corresponding rows in time , since is . The reachability check can be done in time. The cyclicity (checking whether a cycle has been already created) takes the same amount of time by looking for a pair of nodes in , such .

Lemma 4

Algorithm 2 outputs in time the first legal orientation of , and each of the remaining ones with delay.


Before calling the LegalOrientations procedure we have to compute the reachability matrix from scratch and this costs time. In the following we will bound the delay between two outputs returned by the LegalOrientations procedure. Firstly, note that each call produces at least one solution. This is true when since we have two possible legal orientations of . Before performing any call at depth , the caller function checks whether this will produce at least one solution. Only calls that will produce at least one solution are then performed. This means that in the recursion tree, every internal node has at least a child and each leaf corresponds to a solution. Hence the delay between any two consecutive solutions is bounded by the cost of a leaf-to-root path and the cost of a root-to-the-next-leaf path in the recursion tree induced by LegalOrientations. Since the height of the recursion tree is , i.e. the edges of , and the cost of each recursion node is , we can conclude that the delay between any two consecutive solutions is bounded by . As it can be seen, it is crucial that the size of is (poly)logarithmic. ∎

Input: acyclic, a cycle with
Output: All the legal orientations
Build the reachability matrix for the nodes of in
Let , where by definition
Execute LegalOrientations
[3mm] Procedure LegalOrientations()
       if then
            output and its set of broken edges
             , updated by adding the arc ;
             if is cyclic or has positive reachability test on then
                   LegalOrientations (
             updated adding the arc ;
             if is cyclic or has positive reachability test on then
                   LegalOrientations (
             if is a chain edge then
                   if is cyclic or has positive reachability test on then
                         LegalOrientations (
Algorithm 2 Returning all legal orientations of
Lemma 5 (Correctness)
  1. All the extended cyclic orientations of are output.

  2. Only extended cyclic orientations of are output.

  3. There are no duplicates.

  1. Any extended cyclic orientation can be seen as the union of and , which are two edge disjoint directed subgraphs. Our algorithm enumerates all the extended orientations of , and, for each of them, all legal extended orientations : if there is a cycle in involving only edges in all the extended orientations of are legal; otherwise just the extended orientations of whose arcs create a cycle in are legal. Hence any extended cyclic orientation is output.

  2. Any output solution is an extended orientation: each edge in and in has exactly one direction or is broken. Moreover, any output solution contains at least a cycle: if there is not a cycle in , a cycle is created involving the edges in .

  3. All the extended orientations in output differ for at least an arc in or an arc in . Hence there are no duplicate solutions.

As a result, we obtain delay .

Lemma 6

The extended cyclic orientations of can be enumerated with delay and space .


Finding extended orientations of can be done with delay. Every time a new has been generated, we apply Algorithm 2. By Lemma 4 we output the first cyclic orientation of with delay and the remaining ones with delay . Hence the maximum delay between any two consecutive solutions is . The space usage is linear in all the phases: in particular in Algorithm 2 the space is , because of the reachability matrix , which is smaller than . ∎

Applying Lemma 6 and Lemma 2, and considering the setup cost in Section 3 ( and ), we can conclude as follows.

Theorem 4.1

Algorithm 1 lists all cyclic orientations of with setup cost , and delay . The space usage is memory cells.

5 Absorbing the setup cost

In this section, we show how to modify our approach to get a setup time equal to the delay, requiring space .

Theorem 5.1

All cyclic orientations of can be listed with setup cost , delay , and space usage of memory cells.

We use and for brevity. Let be the following algorithm that takes time to generate solutions, each with delay, starting from any given cycle of size . This cycle is found by performing a BFS on an arbitrary node , and identifying the shortest cycle containing . Note that is a log-hole as required. Now, if , we stop the setup and run the algorithms in the previous sections setting . The case of interest in this section is when . We take a cyclic orientation of , and then arbitrary orientations of the edges in . The setup cost is time and we can easily output each solution in delay. We denote this set of solutions by .

Also, let be the algorithm behind Theorem 4.1, with a setup cost of and delay (i.e. Algorithm 1). We denote the time taken by to list the first solutions, including the setup cost, by , and this set of solutions by . Since and can have nonempty intersection, we want to avoid duplicates.

We show how to obtain an algorithm that lists all the cyclic orientations without duplicates with setup cost and delay, using space. Even though the delay cost of is larger than that of and by a constant factor, the asymptotic complexity is not affected by this constant, and remains .

Algorithm executes simultaneously and independently the two algorithms and . Recall that these two algorithms take time in total to generate and with delay. However those in are produced after a setup cost of . Hence slows down on purpose by a constant factor , thus requiring time: it has time to find the distinct solutions in and build a dictionary on the solutions in . (Since an orientation can be represented as a binary string of length , a binary trie can be employed as dictionary , supporting each dictionary operation in time.) During this time, outputs the solutions from with a delay of time each, while storing the rest of solutions of in a buffer .

After time, the situation is the following: Algorithm has output the solutions in with setup cost and delay. These solutions are stored in , so we can check for duplicates. We have buffered at most solutions of in . Now the purpose of is to continue with algorithm alone, with delay per solution, avoiding duplicates. Thus for each solution given by , algorithm suspends and waits so that each solution is output in time: if the solution is not in , outputs it; otherwise extracts one solution from the buffer and outputs the latter instead. Note that if there are still duplicates to handle in the future, then contains exactly solutions from (and is empty when completes its execution). Thus, never has to wait for a non-duplicated solution. The delay is the maximum between and the delay of , hence . The additional space is dominated by that of , namely, memory cells to store up to solutions.

We also have an amortized cost using the lemma below, where and .

Lemma 7

Listing all the extended cyclic orientations of with delay and setup cost implies that the average cost per solution is .


We perform a BFS on an arbitrary node , and identify the shortest cycle that contains . This costs time. Note that is a hole (i.e. it has no chords). Note that a minimum cycle in either is or contains a node in : hence we perform all the BFSs from each node in , as explained in [6] with an overall cost of . The number of extended orientations of is at least . Our setup cost is , with , and the number of solutions is at least . The overall average cost per solution is at most

6 Conclusions

In this paper we considered the problem of efficiently enumerating cyclic orientations of graphs. The problem is interesting from a combinatorial and algorithmic point of view, as the fraction of cyclic orientations over all the possible orientations can be as small as 0 or very close to 1. We provided an efficient algorithm to enumerate the solutions with delay and overall complexity , with being the number of solutions.


  • [1] N. Alon and Z. Tuza. The acyclic orientation game on random graphs. Random Structures & Algorithms, 6(2-3):261–268, 1995.
  • [2] V. C. Barbosa and J. L. Szwarcfiter. Generating all the acyclic orientations of an undirected graph. Information Processing Letters, 72(1):71 – 74, 1999.
  • [3] B. Bollobas. Extremal Graph Theory. Dover Publications, Incorporated, 2004.
  • [4] P. Erdős and L. Pósa. On the maximal number of disjoint circuits of a graph. Publ. Math. Debrecen, 9:3–12, 1962.
  • [5] D. C. Fisher, K. Fraughnaugh, L. Langley, and D. B. West. The number of dependent arcs in an acyclic orientation. Journal of Combinatorial Theory, Series B, 71(1):73 – 78, 1997.
  • [6] A. Itai and M. Rodeh. Finding a minimum circuit in a graph. SIAM Journal on Computing, 7(4):413–423, 1978.
  • [7] D. S. Johnson, C. H. Papadimitriou, and M. Yannakakis. On generating all maximal independent sets. Inf. Process. Lett., 27(3):119–123, 1988.
  • [8] N. Linial. Hard enumeration problems in geometry and combinatorics. SIAM Journal on Algebraic Discrete Methods, 7(2):331–335, 1986.
  • [9] J. Moon. Topics on tournaments. Athena series: Selected topics in mathematics. Holt, Rinehart and Winston, 1968.
  • [10] O. Pikhurko. Finding an unknown acyclic orientation of a given graph. Combinatorics, Probability and Computing, 19:121–131, 1 2010.
  • [11] T. Richardson. A discovery algorithm for directed cyclic graphs. In Proceedings of the Twelfth International Conference on Uncertainty in Artificial Intelligence, UAI’96, pages 454–461, San Francisco, CA, USA, 1996. Morgan Kaufmann Publishers Inc.
  • [12] P. Spirtes. Directed cyclic graphical representations of feedback models. In Proceedings of the Eleventh Conference on Uncertainty in Artificial Intelligence, UAI’95, pages 491–498, San Francisco, CA, USA, 1995. Morgan Kaufmann Publishers Inc.
  • [13] M. B. Squire. Generating the acyclic orientations of a graph. Journal of Algorithms, 26(2):275 – 290, 1998.
  • [14] R. Stanley. Acyclic orientations of graphs. In I. Gessel and G.-C. Rota, editors, Classic Papers in Combinatorics, Modern Birkhäuser Classics, pages 453–460. Birkhäuser Boston, 1987.
Comments 0
Request Comment
You are adding the first comment!
How to quickly get a good reply:
  • Give credit where it’s due by listing out the positive aspects of a paper before getting into which changes should be made.
  • Be specific in your critique, and provide supporting evidence with appropriate references to substantiate general statements.
  • Your comment should inspire ideas to flow and help the author improves the paper.

The better we are at sharing our knowledge with each other, the faster we move forward.
The feedback must be of minimum 40 characters and the title a minimum of 5 characters
Add comment
Loading ...
This is a comment super asjknd jkasnjk adsnkj
The feedback must be of minumum 40 characters
The feedback must be of minumum 40 characters

You are asking your first question!
How to quickly get a good answer:
  • Keep your question short and to the point
  • Check for grammar or spelling errors.
  • Phrase it like a question
Test description