using System.Collections.Generic;
public readonly int From, To;
public Piece(int f, int t)
return new Piece(To, From);
public Vertex(int capacity)
edges = new int[capacity];
public int Add(int piece)
public void RemoveAt(int pos)
edges[pos] = edges[count];
private List<Piece> m_dominos;
private Vertex[] m_edges;
private int[] m_edgeIndexOfPiece;
public void Init(Piece[] dominos, int K)
int N = 2 * dominos.Length;
m_dominos = new List<Piece>(N);
foreach(Piece d in dominos)
m_dominos.Add(d.Mirror());
int [] capacity = new int[K];
foreach(Piece piece in m_dominos)
for (int v = 0; v < K; v++)
m_edges[v] = new Vertex(capacity[v]);
m_edgeIndexOfPiece = new int[N];
for (int nPiece = 0; nPiece < N; nPiece++)
Piece d = m_dominos[nPiece];
int pos = m_edges[vertex].Add(nPiece);
UpdatePosition(vertex, pos);
public void UpdatePosition(int vertex, int edgeIndex)
int nPiece = m_edges[vertex].edges[edgeIndex];
m_edgeIndexOfPiece[nPiece] = edgeIndex;
public void RemoveEdgeAt(int nPiece)
int vertex = m_dominos[nPiece].From;
int pos = m_edgeIndexOfPiece[nPiece];
m_edges[vertex].RemoveAt(pos);
if (pos < m_edges[vertex].count)
UpdatePosition(vertex, pos);
public void RemovePiece(int nPiece)
RemoveEdgeAt(nPiece ^ 1);
public IList<Piece> FindLoop()
if (0 == m_dominos.Count)
int N = m_dominos.Count / 2;
Queue<int> path = new Queue<int>(N);
int vertex = m_dominos[0].From;
while(path.Count < N && nShifts > 0)
if(m_edges[vertex].count > 0)
int nPiece = m_edges[vertex].edges[0];
vertex = m_dominos[nPiece].To;
else if(vertexFrom == vertex)
int nPiece = path.Dequeue();
vertex = m_dominos[nPiece].To;
if (vertexFrom != vertex)
return path.Select(nPiece => m_dominos[nPiece]).ToList();
public static void Main()
Test("simple", new []{ 0,0, 0,1, 0,1, 1,1}, 2);
Test("complex", new []{ 0,0, 0,1, 0,1, 1,1, 0,2, 2,3, 3,0}, 4);
Test("Kenigsberg", new []{ 0,1, 0,1, 0,2, 0,2, 0,3, 1,3, 2,3}, 4);
static void Test(string title, int [] fromto, int K)
int N = fromto.Length / 2;
Piece [] pieces = new Piece[N];
pieces[i] = new Piece(fromto[2*i], fromto[2*i+1]);
DominosKeeper keeper = new DominosKeeper();
IList<Piece> r = keeper.FindLoop();
Console.WriteLine("{0}: No loop found", title);
Console.Write("{0}:", title);
foreach(Piece piece in r)
Console.Write(" ({0},{1})", piece.From, piece.To);