题目

搜索。并且通过题意所得到的信息先推出几个性质。

如果每个字母在开头的出现次数等于结尾的出现次数,则说明每个单词都有可能要成为起点。

而如果有字母在开头的出现次数比结尾的出现次数大,则只有以该字母为开头的单词才有机会成为起点,这样我们就可以只从他们开始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
*/ 
01-25 14:52