传送门:Play on Words
把出现的单词的第一个字母与最后一个字母分别视为以其命名的一个顶点,并在两点之间连一条以第一个字母到最后一个字母的有向边,构建一个图,然后判断是否构成欧拉图即可。
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 26;
int t, n;
int indeg[maxn], outdeg[maxn];
int vis[maxn], g[maxn][maxn];
void init()
{
for(int i = 0; i < maxn; ++i)
{
indeg[i] = 0;
outdeg[i] = 0;
vis[i] = 0;
for(int j = 0; j < maxn; ++j)
g[i][j] = 0;
}
}
void read()
{
string w;
int s, f;
cin >> n;
for(int i = 0; i < n; ++i)
{
cin >> w;
s = w[0] - 'a';
f = w[w.length()-1] - 'a';
++outdeg[s];
++indeg[f];
vis[s] = vis[f] = 1;
g[s][f] = 1;
}
}
void dfs(int u)
{
vis[u] = 0;
for(int i = 0; i < maxn; ++i)
if(vis[i] && g[u][i])
dfs(i);
}
void solve()
{
bool flag = true;
int begNum = 0, endNum = 0, begI = 0;
for(int i = 0; i < maxn; ++i)
if(vis[i])
{
int div = indeg[i] - outdeg[i];
if(div == -1) //起始点
{
++begNum;
begI = i;
}
else if(div == 1) //终止点
++endNum;
else if(div != 0) //不满足欧拉路
flag = false;
}
if(flag)
{
if((begNum == 1 && endNum == 1) || (!begNum && !endNum))
{
dfs(begI);
for(int i = 0; i < maxn; ++i)
if(vis[i])
flag = false;
}
else
flag = false;
}
if(flag)
cout << "Ordering is possible.\n";
else
cout << "The door cannot be opened.\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> t;
while(t--)
{
init();
read();
solve();
}
return 0;
}