搜索。并且通过题意所得到的信息先推出几个性质。
如果每个字母在开头的出现次数等于结尾的出现次数,则说明每个单词都有可能要成为起点。
而如果有字母在开头的出现次数比结尾的出现次数大,则只有以该字母为开头的单词才有机会成为起点,这样我们就可以只从他们开始dfs了。
#include <bits/stdc++.h>
#define N 5011
using namespace std;
string s[N];
int n, cnt, flag, top, lin[N], len[N], sum[N], vis[N], sta[N];
struct edg {
int to, nex;
}e[1000101];
inline void add(int f, int t)
{
e[++cnt].to = t;
e[cnt].nex = lin[f];
lin[f] = cnt;
}
void dfs(int now)
{
vis[now] = 1;
sta[++top] = now;
for (int i = lin[now]; i; i = e[i].nex)
{
int to = e[i].to;
if (vis[to]) continue;
dfs(to);
}
if (top == n)
{
cout << s[sta[1]];
for (int i = 2; i <= top; i++)
cout << "." << s[sta[i]];
exit(0);
}
vis[now] = 0;
top--;
}
void check()
{
int ha1 = 0, ha_1 = 0;
int front = 0;
for (int i = 1; i <= 26; i++)
{
if (sum[i] == 1)
front = i, ha1++;//有几个字符串的sum是1
if (sum[i] == -1)//有几个字符串
ha_1++;
}
if (!ha1 && !ha_1)
for (int i = 1; i <= n; i++)
dfs(i);
else if (ha1 == 1 && ha_1 == 1)
for (int i = 1; i <= n; i++)
if (s[i][0] - 'a' + 1 == front)
dfs(i);
//当然,上面情况也不一定满足,因此要到最后输出***.
printf("***");
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
cin >> s[i];
sort(s + 1, s + 1 + n);
for (int i = 1; i <= n; i++)
len[i] = s[i].size(), sum[s[i][0] - 'a' + 1]++, sum[s[i][len[i] - 1] - 'a' + 1]--;
for (int i = 1; i <= n; i++)
for( int j = n; j >= 1; j--)
if (s[i][len[i] - 1] == s[j][0] && i != j) //保证当前的边一定是从小到大的, 所以要从n到1枚举
add(i, j);
check();
return 0;
}
/*
6
aloha
arachnid
dog
gopher
rat
tiger
*/