对一组单词按照首尾相连进行排序。
要求前一个单词的最后一个字母跟后一个单词的首字母相同。
根据这个意思首先可以联想到每个顶点有且仅有一次,即我们所熟知的汉密尔顿通路。
但是,遇到一个问题。
求汉密尔顿路是复杂的。
所以我们就要将图中的信息进行转化。
把每个单词的首尾两个字母分别看做两个顶点,中间的边看做已知的单词word,然后,汉密尔顿通路的问题就转化成了欧拉路的问题,每个边有且仅有一次。
下面就用并查集进行判断图是否连通,标记各顶点的度数,根据顶点度数的奇偶来确定是否有欧拉路或者欧拉回路即可。
要求前一个单词的最后一个字母跟后一个单词的首字母相同。
根据这个意思首先可以联想到每个顶点有且仅有一次,即我们所熟知的汉密尔顿通路。
但是,遇到一个问题。
求汉密尔顿路是复杂的。
所以我们就要将图中的信息进行转化。
把每个单词的首尾两个字母分别看做两个顶点,中间的边看做已知的单词word,然后,汉密尔顿通路的问题就转化成了欧拉路的问题,每个边有且仅有一次。
下面就用并查集进行判断图是否连通,标记各顶点的度数,根据顶点度数的奇偶来确定是否有欧拉路或者欧拉回路即可。
#include<cstdio> #include<iostream> #include<cstring> using namespace std; const int Maxsize = 30; int root[Maxsize]; int main() { int judge(char a); void init_set(); int find_set(int n); void union_set(int n,int m); int n,m; int cnt; int vis[Maxsize]; int in[Maxsize],out[Maxsize]; char data[1010]; cin>>n; while(n--) { cnt = 0; memset(vis,0,sizeof(vis)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(root,0,sizeof(root)); cin>>m; init_set(); for(int i = 0 ; i < m ; i++) { cin>>data; int len = strlen(data); in[data[0]-'a'+1]++; out[data[len-1]-'a'+1]++; vis[data[0]-'a'+1] = 1; vis[data[len-1]-'a'+1] = 1; union_set(data[0]-'a'+1,data[len-1]-'a'+1); } for(int i = 1 ; i <= 26 ; i++) { if(root[i] == i && vis[i]) { cnt++; } } int f = 0,l = 0,flag = false; if(cnt > 1) { printf("The door cannot be opened.\n"); } else { for(int i = 1; i <= 26 ; i++) { if(in[i] - out[i] == 1)f++; else if(out[i] - in[i] == 1)l++; else if(out[i] - in[i] == 0)continue; else flag = true; } if(flag)printf("The door cannot be opened.\n"); else if(f<=1 && l <= 1)printf("Ordering is possible.\n"); else printf("The door cannot be opened.\n"); } } return 0; } void init_set() { for(int i = 1 ; i <= 26 ; i++) { root[i] = i; } } int find_set(int n) { if(root[n] != n) { root[n] = find_set(root[n]); } return root[n]; } void union_set(int n,int m) { if(find_set(n) != find_set(m)) { root[m] = find_set(n); } }