题目:输入n个单词,是否可以把这些所有单词排成一个序列,使得每个单词的第一个字母和上一个单词的最后一个字母想同。
有向图欧拉回路:1,图连通.2,所有定点入度等于出度
有向图欧拉通路:1,图连通.2,仅有两个奇度定点,其中一个入度比出度大1,另一个定点出度比入度大1
思路:可以把一个单词看作一条边,单词的首尾两个字母为定点,建立无向图(即G[u][v]=G[v][u]=1),因为欧拉回路和欧拉通路的条件都必须是连通图,也就是有向图的底图无向图必须是连通图。
可以用dfs来判断无向图是否连通,先从一个定点开始dfs,每访问一条边,就删除一条边,即G[u][v]--,G[v][u]--,最后判断所有定点是否被访问到,如果全部被访问到,则图连通,反之不连通。
接下来就是判断两个条件:
(1)所有定点入度等于出度
(2)仅有两个奇度定点,其中一个入度比出度大1,另一个定点出度比入度大1
只有当图连同,(1)和(2)有一个成立,就说明是欧拉回路或者欧拉通路。
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.Vector;
public class Main {
static int maxn = 26;
static int[][] G = new int[maxn][maxn];
static int[] in = new int[maxn];
static int[] out = new int[maxn];
static boolean[] vis = new boolean[maxn];
static int start;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int T = scan.nextInt();
while(T--!=0){
Arrays.fill(vis, false);
Arrays.fill(in, 0);
Arrays.fill(out, 0);
Set<Integer> set = new HashSet<>();
for(int i=0;i<maxn;i++){
Arrays.fill(G[i], 0);
}
int n = scan.nextInt();
for(int i=0;i<n;i++){
String str = scan.next();
int u = str.charAt(0)-'a';
int v = str.charAt(str.length()-1)-'a';
G[u][v]++;
G[v][u]++;
out[u]++;
in[v]++;
start = u;
}
//判断图是否连通
dfs(start);
boolean isDfs = true;
for(int i=0;i<maxn;i++){
if(in[i]+out[i]>0&&vis[i]==false){
isDfs = false;
}
}
boolean flag1=true,flag2=true;
//判断是不是所有顶点入度等于出度
for(int i=0;i<maxn;i++){
if(in[i]!=out[i]){
flag1 = false;
}
}
Vector<Integer> v = new Vector<>();
int cnt = 0;
//判断是不是有两个奇度定点
for(int i=0;i<maxn;i++){
if((in[i]+out[i])%2!=0){
v.add(i);
}
if(in[i]==out[i])cnt++;
}
if(v.size()!=2){
flag2 = false;
}else{
int a = v.get(0);
int b = v.get(1);
if(!((in[a]-out[a]==1&&out[b]-in[b]==1)
||(in[b]-out[b]==1&&out[a]-in[a]==1))){//看两个奇度顶点是不是满足有向图欧拉通路的条件
flag2 = false;
}
}
if(cnt!=24){
flag2 = false;
}
if(isDfs){
if(flag1||flag2){
System.out.println("Ordering is possible.");
}else{
System.out.println("The door cannot be opened.");
}
}else{
System.out.println("The door cannot be opened.");
}
}
}
public static void dfs(int u){
vis[u] = true;
for(int v=0;v<maxn;v++){
if(G[u][v]>0){
G[u][v]--;
G[v][u]--;
dfs(v);
}
}
}
}