对于本题,为什么先建图然后分别对每个邻接表排序是错的,修改为对整个单词数组排序后再建图即可通过。
以下是代码,标记 new 的代码是正确解法,标记 old 的代码是对每个邻接表分别排序的错解。
#include <iostream>
#include <algorithm>
#include <vector>
#include <numeric>
#include <bitset>
using namespace std;
const int N = 1010, M = 30, LIM = 26;
int n, from, to, ind[M], outd[M];
string s[N], minn;
vector<pair<int, int> > g[M];
basic_string<int> tmp, ans;
bitset<N> vis;
bool flag;
void dfs(int u) {
if (tmp.size() == n) {
flag = true;
for (auto v : tmp) ans += v;
return;
} for (auto [v, w] : g[u]) {
if (flag) break;
if (vis[w]) continue;
tmp += w;
vis[w] = true;
dfs(v);
tmp.pop_back();
vis[w] = false;
}
}
bool operator<(pair<int, int> a, pair<int, int> b) {
return s[a.second] < s[b.second];
}
int main() {
cin.tie(nullptr);
ios::sync_with_stdio(false);
cin >> n;
for (int i = 1; i <= n; ++i) cin >> s[i];
sort(s + 1, s + n + 1); // new
for (int i = 1; i <= n; ++i) {
// if (i == 1) minn = s[i]; // old
// else minn = min(minn, s[i]); // old
from = s[i].front() - 'a' + 1, to = s[i].back() - 'a' + 1;
g[from].push_back({to, i});
++ind[to], ++outd[from];
} from = to = 0;
for (int i = 1; i <= LIM; ++i) {
if (ind[i] - outd[i] == 1 && !to) to = i;
else if (outd[i] - ind[i] == 1 && !from) from = i;
else if (ind[i] != outd[i]) {
cout << "***\n";
return 0;
}
} minn = s[1]; // new
if (!from) from = minn.front() - 'a' + 1;
// for (int i = 1; i <= LIM; ++i) sort(g[i].begin(), g[i].end()); // old
dfs(from);
if (ans.size() != n) cout << "***\n";
else for (int i = 0; i < ans.size(); ++i)
cout << s[ans[i]] << ".\n"[i == ans.size() - 1];
return 0;
}