题意:输入n个单词,如果单词a的最后一个字母和单词b的第一个字母一样,这两个单词就可以连接起来。问是否可以把所有的单词连接起来。
思路:欧拉通路。对于有向图,欧拉通路存在有两个必要条件,一是图连通,二是所有顶点的入度和出度相等,或者有两个顶点例外,一个出度比入度大1,另一个入度比出度大1。统计每个字母在单词首尾出现的次数,可以解决条件二,然后根据这一步的结果,找一个起点,对图进行dfs,如果能访问到所有的顶点,说明图连通。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#define INF 1000000010
#define ll long long
#define max3(a,b,c) max(a,max(b,c))
#define MAXN 1000
using namespace std;
char str[1024];
int rudu[26];
int chudu[26];
int g[680][680];
int cnt[680];
inline int hash(char a,char b){
return (a-'a')*26+b-'a';
}
void dfs(int x){
cnt[x]--;
for(int i=0;i<676;i++){
if( (x%26==i/26)&&cnt[i] ) {
dfs(i);
}
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(rudu,0,sizeof(rudu));
memset(chudu,0,sizeof(chudu));
memset(cnt,0,sizeof(cnt));
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",str);
++rudu[str[0]-'a'];
++chudu[ str[strlen(str)-1]-'a' ];
++cnt[ hash(str[0],str[strlen(str)-1]) ];
}
bool ok=false;
vector<int> test;
for(int i=0;i<26;i++){
if( rudu[i]-chudu[i]!=0 ){
test.push_back(i);
}
}
int start;
if(test.size()==0){
ok=true;
for(int i=0;;i++)
if(cnt[i]){
start=i;
break;
}
}
if(test.size()==2&& (rudu[test[0]]-chudu[test[0]]==1) && (chudu[test[1]]-rudu[test[1]]==1) ){
ok=true;
for(int i=26*test[0];;i++)
if(cnt[i]){
start=i;
break;
}
}
if(test.size()==2&& (rudu[test[0]]-chudu[test[0]]==-1) && (chudu[test[1]]-rudu[test[1]]==-1) ){
ok=true;
for(int i=26*test[1];;i++)
if(cnt[i]){
start=i;
break;
}
}
if(ok){
dfs(start);
for(int i=0;i<676;i++){
if(cnt[i])ok=false;
}
}
if(ok){
cout<<"Ordering is possible."<<endl;
}else{
cout<<"The door cannot be opened."<<endl;
}
}
}