——by A Code Rabbit
Description
输入一些单词,要求把这些所有的单词都用成语接龙的办法连起来。输出可能或者不可能。
Types
Date Structure :: Graphs
Analysis
对于每个单词,有价值的就是第一个单词和最后一个单词。
虽然输入数据可能高达100000个,但是字母只有26个。
可以以这些字母为点,把这题的模型化为有向图。
然后题目所求的就是这无向图的一个欧拉路径。要求欧拉路径,可以计算每个点的入度和出度,容易理解除了第一个单词开头的字母,和最后一个单词结尾的字母,其他的字母入度和出度必然相等。
而第一个单词开头的字母和最后一个单词结尾的字母,前者入度比出度大一,后者出度比入度小一。
不过要记得,当所有点的入度和出度都相等,即构成欧拉回路,也符合题目的要求。
最后别忘了这个定理成立的条件——这个图的无向图,必须是连通的。
DFS 一下某个点的连同分支是否可以到达每个点即可。
Solution
// 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;
}
参考资料:无