描述
给你一些单词,请你判断能否把它们首尾串起来串成一串。
前一个单词的结尾应该与下一个单词的道字母相同。
如
aloha
dog
arachnid
gopher
tiger
rat
可以拼接成:aloha.arachnid.dog.gopher.rat.tiger
输入
第一行是一个整数N(0<N<20),表示测试数据的组数
如果存在拼接方案,请输出所有拼接方案中字典序最小的方案。(两个单词之间输出一个英文句号".")
如果不存在拼接方案,则输出
2
6
aloha
arachnid
dog
gopher
rat
tiger
3
oak
maple
elm
样例输出
aloha.arachnid.dog.gopher.rat.tiger
给你一些单词,请你判断能否把它们首尾串起来串成一串。
前一个单词的结尾应该与下一个单词的道字母相同。
如
aloha
dog
arachnid
gopher
tiger
rat
可以拼接成:aloha.arachnid.dog.gopher.rat.tiger
输入
第一行是一个整数N(0<N<20),表示测试数据的组数
每组测试数据的第一行是一个整数M,表示该组测试数据中有M(2<M<1000)个互不相同的单词,随后的M行,每行是一个长度不超过30的单词,单词全部由小写字母组成。
如果存在拼接方案,请输出所有拼接方案中字典序最小的方案。(两个单词之间输出一个英文句号".")
如果不存在拼接方案,则输出
***
2
6
aloha
arachnid
dog
gopher
rat
tiger
3
oak
maple
elm
样例输出
aloha.arachnid.dog.gopher.rat.tiger
***
想到了跟路径有关,但是没想到跟欧拉路有关。。
每个单词的开头和结尾都存为一个点,这样就看做一个图,对其进行欧拉路判断,并且储存路径。
注意欧拉路的判断:
【对于有向图G,具有一条单向欧拉路,当且仅当G是连通的,且每个结点入度等于出度
或者
除两个结点外,每个结点的入度等于出度,而这两个结点满足,一个结点的入度比出度大1,另一个结点的入度比出度小1。】
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
bool vis[1005];
int degree_in[30], degree_out[30], order[1005];
int n;
struct node
{
char str[35];
int start, over;
};
node word[1005];
bool cmp(node a, node b)
{
return strcmp(a.str, b.str) < 0;
}
int confirm()
{
int x_out, x_in;
int ans;
x_out = x_in = 0;
for (int i = 0; i < 26; ++i)
{
if (abs(degree_in[i] - degree_out[i]) >= 2)///只要出现多于两个的就结束
return -1;
else if (degree_in[i] - degree_out[i] == 1)
x_in++;
else
if (degree_in[i] - degree_out[i] == -1)
{
x_out++;
ans = i;
}
}
if (x_in > 1 || x_out > 1)
return -1;
else if (x_in == 0)///此时随便找个就可以
{
for (int i = 0; i < 26; ++i)
{
if (degree_out[i] != 0)
return i;
}
}
return ans;
}
bool DFS(int start, int counts)
{
if (counts == n)
return true;
for (int i = 0; i < n; ++i)
{
if (word[i].start < start || vis[i])
continue;
else if (word[i].start > start)
return false;
vis[i] = true;
order[counts] = i;
if (DFS(word[i].over, counts+1))
return true;
vis[i] = false;
}
return false;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
memset(vis, false, sizeof(vis));
memset(degree_in, 0, sizeof(degree_in));
memset(degree_out, 0, sizeof(degree_out));
scanf("%d", &n);
for (int i = 0; i < n; ++i)
{
scanf("%s", word[i].str);
int len = strlen(word[i].str);
word[i].start = word[i].str[0] - 'a';
word[i].over = word[i].str[len-1] - 'a';
degree_in[word[i].str[len-1]-'a']++;
degree_out[word[i].str[0]-'a']++;
}
int start = confirm();
if (start == -1)
{
printf("***\n");
continue;
}
sort(word, word+n, cmp);
if (!DFS(start, 0))
{
printf("***\n");
continue;
}
printf("%s", word[order[0]].str);
for (int i = 1; i < n; ++i)
printf(".%s", word[order[i]].str);
puts("");
}
return 0;
}