题目链接:https://vjudge.net/problem/UVA-10129
代码如下:
// UVa10129 Play on Words // Rujia Liu // 题意:输入n个单词,是否可以排成一个序列,使得每个单词的第一个字母和上一个单词的最后一个字母相同 // 算法:把字母看作结点,单词看成有向边,则有解当且仅当图中有欧拉路径。注意要先判连通 #include<cstdio> #include<cstring> #include<vector> using namespace std; const int maxn = 10000 + 5; int pa[256], used[256], deg[256]; // 是否出现过;度数 char word[maxn]; int n, cc; int findset(int x) { return ( pa[x] != x ? pa[x] = findset(pa[x]) : x ); } void init() { memset(used, 0, sizeof(used)); memset(deg, 0, sizeof(deg)); for(int ch = 'a'; ch <= 'z'; ch++) pa[ch] = ch; // 初始化并查集 cc = 26; // 连通块个数 } void solve() { scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%s", word); char c1 = word[0]; char c2 = word[strlen(word)-1]; deg[c1]++; deg[c2]--; used[c1] = used[c2] = 1; int s1 = findset(c1); int s2 = findset(c2); if(s1 != s2) { pa[s1] = s2; cc--; } } vector<int> d; for(int ch = 'a'; ch <= 'z'; ch++) { if(!used[ch]) cc--; // 没出现过的字母 else if(deg[ch] != 0) d.push_back(deg[ch]); } int ok = false; if(cc == 1 && (d.empty() || (d.size() == 2 && (d[0] == 1 || d[0] == -1)))) ok = true; if(ok) printf("Ordering is possible. "); else printf("The door cannot be opened. "); } int main() { int T; scanf("%d", &T); while(T--) { init(); solve(); } return 0; }