大体题意:
给你n个单词,问是否可以首尾相连,就是单词接龙!
思路:
看了下LRJ写的,用到了并查集判断有向图是否连通。
单词可以根据首字母,尾字母进行分类集合,最多26个集合!字母看作结点,单词看成有向边。
有解的情况:
1.必须连通
2.出度不等于入度的只能有0个或者2个!
有两个的情况还必须满足,一个出度比入度大1 (起点),入度比出度大1(终点)!
可以用lef表示剩余的连通图,当lef为1的时候表示可以连通!
然后把度数弄到deg数组里,入度++,出度--。
最后看是否为0.
#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int maxn = 1000 + 10;
char str[maxn];
int is_use[26],pa[26],deg[26];
int findset(int x){return pa[x] == x ? x : pa[x] = findset(pa[x]);}
int main()
{
int T,N;
scanf("%d",&T);
while(T--){
for (int i = 0; i < 26; ++i)pa[i] = i;
memset(deg,0,sizeof(deg));
memset(is_use,0,sizeof(is_use));
scanf("%d",&N);
int lef = 26;
for (int i = 0; i < N; ++i){
scanf("%s",str);
char ch1 = str[0],ch2 = str[strlen(str)-1];
deg[ch1-'a']++;deg[ch2-'a']--;
is_use[ch1-'a'] = is_use[ch2-'a'] = 1;
int s1 = findset(ch1-'a'),s2 = findset(ch2-'a');
if (s1 != s2){--lef;pa[s1] = s2;}
}
vector<int >d;
for (int i = 0; i < 26; ++i){
if (!is_use[i])--lef;
else if (deg[i])d.push_back(deg[i]);
}
bool ok = false;
if (lef == 1 && d.empty())ok=true;
else if (d.size() == 2 && lef == 1 && ((d[0] == 1 && d[1] == -1) || (d[1] == 1 && d[0] == -1)))ok=true;
if (!ok)printf("The door cannot be opened.\n");
else printf("Ordering is possible.\n");
}
return 0;
}