LRJ-Example-06-16-Uva10129
#include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn = 1000 + 5; // at most 1000 lowercase characters // union find set, each set is a tree // only letters 'a' through 'z' will appear, so totally 26 nodes const int maxc = 26; int parent[maxc]; // parent of each node // find the root node of the set of node x int findSet(int x) { return parent[x] == x ? x : findSet(parent[x]); } int used[maxc]; int degree[maxc]; // degree = out degree - in degree int main() { int T; int N; // 1 <= N <= 100000 char word[maxn]; scanf("%d", &T); while(T--) { scanf("%d", &N); memset(used, 0, sizeof(used)); memset(degree, 0, sizeof(degree)); // init the sets for(int i = 0; i < maxc; i++) parent[i] = i; int numSet = maxc; for(int i = 0; i < N; i++) { // read each word scanf("%s", word); int first = word[0] - 'a'; int last = word[strlen(word) - 1] - 'a'; // there is an edge first --> last degree[first]++;// out degree degree[last]--;// in degree used[first] = used[last] = 1; int setFirst = findSet(first); int setLast = findSet(last); if(setFirst != setLast) { // union parent[setFirst] = setLast; numSet--; } } vector<int> d; for(int i = 0; i < maxc; i++) { if(!used[i]) numSet--; else if (degree[i] != 0) d.push_back(degree[i]); } bool ok = false; if(numSet == 1 && // all nodes are connected // Euler circuit, all nodes have degree 0 (d.empty() || // Euler path, if d[0] == 1, then d[1] == -1, and vice versa (d.size() == 2 && (d[0] == 1 || d[0] == -1)))) ok = true; if(ok) printf("Ordering is possible.\n"); else printf("The door cannot be opened.\n"); } return 0; }