給你一些單詞,請你判斷能否把它們首尾串起來串成一串。
前一個單詞的結尾應該與下一個單詞的道字母相同。
如
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;
}