题解 P1127 【词链】
蒟蒻第一篇题解,写的不好还望见谅。
本蒟蒻看到这个题的第一反应就是深搜(似乎建个图会更简单),为了减少循环次数,首先按照字典序排序,建了一个数组 start 标记每个英文首字母出现的位置。将所有字符串都作为dfs起点,再找到所有以前一个末尾开头的字符串dfs下去,然后就得到了2个大大的TLE。没错,不是所有字符串都能作为起点的。
查阅了一点资料,发现如果有1个字母在首位出现次数比末尾出现次数多一,那么这个字母必将是起始字符串的首字母。如果有两个或以上个这样的字母,那么不可解。如果没有这样的字母,说明形成了Hamilton回路,每个字母对应的所有字符串都可以做dfs起点。最后AC,代码在下面。
PS:这道题好像条件有点水,有些代码有问题也能过,不知道我的代码有没有问题,希望评论区大佬指点一下。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int n; int start[30], s1[30];
string choose[1005]; string s[1005]; bool vis[1005];
void dfs(string s_now, int acc){
if(acc == n){
for(int i = 1; i <= n-1; i++){
cout<<choose[i]<<".";
}
cout<<choose[n];
exit(0);
return;
}
char c_now = s_now[s_now.length()-1];
for(int i = start[c_now - 'a']; i; i++){
if(s[i][0] != c_now) break;
if(vis[i]) continue;
choose[acc+1] = s[i];
vis[i] = 1;
dfs(s[i], acc+1);
vis[i] = 0;
}
}
int main(){
cin>>n;
for(int i = 1; i <= n; i++){
cin>>s[i];
s1[s[i][0]-'a']++;
s1[s[i][s[i].length()-1]-'a']--;
}
sort(s+1, s+n+1);
for(int i = 1; i <= n; i++){
if(start[s[i][0]-'a'] == 0)
start[s[i][0]-'a'] = i;
}
int k = 0, h;
for(int i = 0; i < 26; i++){
if(s1[i] == 1) k++, h = i;
if(s1[i] == 2 || k == 2) break;
}
if(k == 1){
for(int i = 1; i <= n; i++){
if(s[i][0] - 'a' == h){
string s_now = s[i];
choose[1] = s[i];
vis[i] = 1;
dfs(s_now, 1);
vis[i] = 0;
}
}
}
if(k == 0){
for(int i = 1; i <= n; i++){
choose[1] = s[i];
vis[i] = 1;
dfs(s[i], 1);
vis[i] = 0;
}
}
cout<<"***";
}