欧拉路径经典问题,
给一些字符串, 要求验证字符串之间是否存在欧拉路径
题意能化简就化简, 其实字符串只看首尾字母即可, 各代表一个顶点, 一个字符串就是一条边
然后就是欧拉路径的通解法,
对于无向图只需要验证连通性, 并且奇数度的顶点只能有2个(一个起点一个终点形成欧拉路径) 或 0个(形成欧拉回路)
对于本题中的有向图, 除了连通性, 除了起点和终点之外, 各个顶点的出度和入度必须相等
并且起点的出度一定比入度大1, 终点的入度比出度大1( 形成欧拉路径)
还有一种特殊情况就是所有顶点的出度和入度相等( 形成欧拉回路 )
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <list>
#include <cassert>
#include <iomanip>
using namespace std;
const int MAXN = 26;
const int BASE = 10;
typedef long long LL;
/*
uva 10129
关键: 1. 对于有向图, Euler Path 除了起点和终点之外, 其他点的出度和入度必须相等,
而且起点的出度恰好比入度大1, 终点的入度恰好比出度大1
或者形成 Euler Circuit, 即所有点的出度和入度都相等
2. 对于无向图(此题为有向图), Euler Path 奇数度的点(奇点)个数等于0或2即可
3. 要考虑到只有一个word的情况
*/
int T, n, cnt;
int Edge[MAXN][MAXN];
int in[MAXN],out[MAXN];
void DFS(int v){
for(int i=0; i<MAXN; i++){
if( Edge[v][i] ){
cnt++;
Edge[v][i]--;
DFS(i);
}
}
}
int main(){
cin >> T;
string str;
while( T-- ){
bool res = true;
memset(Edge,0,sizeof(Edge));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
cin >> n;
for(int i=0; i<n; i++){
cin >> str;
out[*str.rbegin()-'a']++;
in[*str.begin()-'a']++;
Edge[*str.rbegin()-'a'][*str.begin()-'a']++;
}
int notEqual = 0;
cnt = -1;
for(int i=0; i<MAXN; i++){
if( in[i] != out[i] ){
notEqual++;
if( in[i]-out[i]!=1 && out[i]-in[i]!=1 ){ //是起点或终点, 不算notEqual
// cout << "false1" << endl;
res = false;
break;
}else notEqual--;
if( out[i]-in[i]==1 ){
cnt = 0;
DFS(i);
}
}
}
if( res && cnt==-1 ){
for(int i=0; i<MAXN; i++){
if( out[i]>0 ){
cnt = 0;
DFS(i);
break;
}
}
}
if( res && notEqual!=0 || cnt!=n ){ // 无欧拉回路 或 不连通
// cout << "false2" << endl;
res = false;
}
if( res ) cout << "Ordering is possible." << endl;
else cout << "The door cannot be opened." << endl;
}
return 0;
}