题目: 给你多个单词,问你能不能将所有单词组成这样一个序列:序列的前一个单词的尾字母与后一个单词的头字母相同.
思路:将单词看成有向边,字母看成结点,转化为判断有向图是否有欧拉路。必须满足弱连通,全部顶点度数相同或者有两个点一个入度比出度大一,一个出度比入度大一
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <cmath>
#include <cctype>
using namespace std;
#define maxn 100000+10
#define LL long long
int cas=1,T;
int pre[maxn];
int in[maxn];
int out[maxn];
int Find(int x)
{
return pre[x]==-1?x:pre[x]=Find(pre[x]);
}
int main()
{
//freopen("in","r",stdin);
scanf("%d",&T);
while (T--)
{
int n;
scanf("%d",&n);
memset(pre,-1,sizeof(pre));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
for (int i = 0;i<n;i++)
{
char str[1005];
scanf("%s",&str);
int u = str[0]-'a';
int v = str[strlen(str)-1]-'a';
in[u]++;
out[v]++;
u = Find(u);
v = Find(v);
if (u!=v)
pre[u]=v;
}
int cnt = 0;
for (int i = 0;i<26;i++)
if ((in[i] || out[i]) && Find(i)==i)
cnt++;
if (cnt>1)
{
puts("The door cannot be opened.");
continue;
}
int c1=0;
int c2=0;
int c3=0;
for (int i = 0;i<26;i++)
{
if (in[i]==out[i])
continue;
else if (in[i]-out[i]==1)
c2++;
else if (out[i]-in[i]==1)
c3++;
else
c1++;
}
if (((c2==0&&c3==0) || (c2==1&&c3==1)) && c1==0)
puts("Ordering is possible.");
else
puts("The door cannot be opened.");
}
//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
return 0;
}