大体题意:
给你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; }