//
// main.cpp
// uva 10129 Play on Words
//
// Created by XD on 15/7/19.
// Copyright (c) 2015年 XD. All rights reserved.
//
//注意欧拉图的定义,此题中需要用到欧拉图和半欧拉图的定义
//解题思路 :每个单词可以看成是一条从首字母到最后的那个字母的一条边形成一个图,要是能够按照题目的要求将所有单词连接在一起,则要求图是欧拉图或是欧拉图,然后则可以根据定理来解决这个问题,判断弱连通性则可以使用并查集来计算,判断强连通性可以使用如下的规则
/*
1.从某个节点s开始广度优先遍历,若不能遍历所有的点,则说明不是强连通图
2.求原图的逆图
3.从节点s开始广度遍历,若能够遍历所有的点,说明原图是强连通图,反之则不是。
*/
//
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <string.h>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
using namespacestd ;
int din[30] ;
int dout[30] ;
set<int > v ;
int g[30][30] ;
int flag[30] ;
//带秩和路劲压缩的并查集
int p[30] ;
int r[30] ;
void init()
{
for (int i = 0; i < 30; i++) {
p[i] = i;
r[i] = 0 ;
}
}
int find_set(int x)
{
if (p[x] != x) {
p[x] =find_set(p[x]) ;
}
returnp[x] ;
}
void link(int x ,int y)
{
if (r[x] >r[y]) {
p[y] = x ;
}else{
p[x] = y ;
if (r[x] ==r[y]) {
r[y]+=1 ;
}
}
}
void UNION(int x ,int y )
{
link(find_set(x) ,find_set(y)) ;
}
//广度优先遍历
bool bfs(int x,int n )
{
queue<int > q ;
q.push(x) ;
flag[x]=1 ;
int num =1 ;
while (!q.empty()) {
int first = q.front() ;q.pop() ;
for (int i = 0 ;i < 26 ; i++) {
if (g[first][i] == 0) {
continue ;
}
int to = i;
if (flag[to] == 0) {
flag[to] = 1 ;
q.push(to) ;
num++ ;
}
}
}
if (num == n) {
returntrue ;
}
returnfalse ;
}
//矩阵转置
void inverse()
{
for (int i = 0; i < 30; i++) {
for (int j = i; j < 30; j++) {
int temp =g[i][j] ;
g[i][j] =g[j][i] ;
g[j][i] =temp ;
}
}
}
int main() {
int casenum ;
int n ;
char s[1010] ;
int odd ;
scanf("%d" ,&casenum) ;
int temp = 0 ;
while (casenum--) {
//初始化
memset(flag, 0,sizeof(flag)) ;
memset(g, 0,sizeof(g)) ;
v.clear() ;
memset(din, 0,sizeof(din)) ;
memset(dout, 0,sizeof(dout)) ;
scanf("%d" , &n) ;
init() ;
int u,t ;
for (int i= 0 ; i < n ; i++) {
scanf(" %s" , s) ;
u = s[0]-'a' ; t = s[strlen(s)-1]-'a' ;
dout[u]++ ;din[t]++ ;
temp = u ;
if(find_set(u) !=find_set(t))
{
UNION(u, t) ;
}
g[u][t] =1 ;
v.insert(u) ;v.insert(t ) ;
}
//统计奇数度点的个数
odd= 0 ;
int flag1 = 0;
for(set<int >::iterator it = v.begin() ; it!=v.end() ; it++)
{
if (din[*it]!=dout[*it])
{
if((din[*it]+dout[*it]) % 2 == 1)
{
odd++ ;
if (odd > 2 ||din[*it] - dout[*it] > 1 ||din[*it] - dout[*it] <-1 ) {
flag1=1 ;
break ;
}
}
else{
flag1 = 1;
break ;
}
}
}
if(flag1 == 1)
{
printf("The door cannot be opened.\n") ;
continue ;
}
//是不是欧拉图
if (odd == 0) {
if (!bfs(temp, (int )v.size())){
printf("The door cannot be opened.\n") ;
continue ;
}
inverse() ;
memset(flag, 0,sizeof(flag)) ;
if (!bfs(temp, (int )v.size())){
printf("The door cannot be opened.\n") ;
continue ;
}
printf("Ordering is possible.\n" ) ;
}
//半欧拉图
elseif(odd == 2){
temp = -1 ;
flag1 = 0 ;
for(set<int >::iterator it = v.begin() ; it!=v.end() ; it++)
{
if (temp == -1) {
temp =find_set(*it) ;
}
else{
if(find_set(*it) != temp ){
flag1 = 1 ;
break ;
}
}
}
if (flag1 == 1) {
printf("The door cannot be opened.\n") ;
continue ;
}
printf("Ordering is possible.\n" ) ;
}
else{
printf("The door cannot be opened.\n") ;
}
}
return 0;
}