——by A Code Rabbit
Date Structure :: Graphs
对于每个单词,有价值的就是第一个单词和最后一个单词。
虽然输入数据可能高达100000个,但是字母只有26个。
可以以这些字母为点,把这题的模型化为有向图。
然后题目所求的就是这无向图的一个欧拉路径。要求欧拉路径,可以计算每个点的入度和出度,容易理解除了第一个单词开头的字母,和最后一个单词结尾的字母,其他的字母入度和出度必然相等。
而第一个单词开头的字母和最后一个单词结尾的字母,前者入度比出度大一,后者出度比入度小一。
不过要记得,当所有点的入度和出度都相等,即构成欧拉回路,也符合题目的要求。
最后别忘了这个定理成立的条件——这个图的无向图,必须是连通的。
DFS 一下某个点的连同分支是否可以到达每个点即可。
// UVaOJ 10129 // Play on Words // by A Code Rabbit #include <cstdio> #include <cstring> const int LIMITS = 2000; int t; char word[LIMITS]; int n; bool graph[30][30]; bool is_existing[30]; int difference[30]; // It means the in_order minus the out_order. bool is_visited[30]; void Process(char* word); bool MatchCondition(); int Search(int pos); int main() { scanf("%d", &t); while (t--) { // INIT. memset(difference, 0, sizeof(difference)); memset(graph, false, sizeof(graph)); memset(is_existing, false, sizeof(is_existing)); memset(is_visited, false, sizeof(is_visited)); // Inputs and count. scanf("%d", &n); getchar(); while (n--) { gets(word); // Processing string. Process(word); } // Compete the number of letters. int num_letters = 0; for (int i = 0; i < 26; ++i) { if (is_existing[i]) { ++num_letters; } } // Judge whether in_order and out_order match condition. bool can_order = MatchCondition(); // Judge whether the graph without direction is a connected graph. if (can_order) { for (int i = 0; i < 26; ++i) { if (is_existing[i]) { if (num_letters != Search(i)) { can_order = false; } break; } } } // Outputs. printf("%s\n", can_order ? "Ordering is possible." : "The door cannot be opened."); } return 0; } void Process(char *word) { int first = word[0] - 'a'; int last = word[strlen(word) - 1] - 'a'; ++difference[first]; --difference[last]; graph[first][last] = true; graph[last][first] = true; is_existing[first] = true; is_existing[last] = true; } bool MatchCondition() { int num_nonzero = 0; int num[26]; for (int i = 0; i < 26; ++i) { if (difference[i]) { num[num_nonzero++] = difference[i]; } } if (num_nonzero == 0) { return true; } if (num_nonzero != 2) { return false; } if ((num[0] == -1 && num[1] == 1) || (num[0] == 1 && num[1] == -1)) { return true; } else { return false; } } int Search(int pos) { if (is_visited[pos]) { return 0; } is_visited[pos] = true; int sum = 1; for (int i = 0; i < 26; ++i) { if (graph[pos][i]) { sum += Search(i); } } return sum; }
下载PDF
参考资料:无