词链

xiaoxiao2025-06-20  8

题目

https://www.luogu.org/problemnew/show/P1127

思路

1.单词作点 可以拼在一起的单词连边。

2.先对单词排序,加边时注意顺序,使找到的第一个欧拉回路即为字典序最小的,后面直接跳出就好了。

3.dfs前初步判断一下是否有解(注意,是初步!!!) 用一些奇怪的方法

4.dfs后,若找到解则输出,否则***。(因为初步判断有解时可能将一些无解的情况放过了)

代码

#include <iostream> #include <string> #include <algorithm> using namespace std; const int N=1010,inf=1<<29; int n,len[N],sta[N],cnt[30],top=0; int head[N],to[N*N],next[N*N],en; bool flag=false,vis[N]; string s[N]; void dfs(int u) { if (flag) return ; sta[top++]=u; vis[u]=true; int v; for (int i=head[u];i;i=next[i]) { v=to[i]; if (!vis[v]) dfs(v); } if (top==n) flag=true; else vis[u]=false,--top; } void add_edge(int u,int v){ to[++en]=v,next[en]=head[u],head[u]=en; } int main() { cin>>n; for (int i=1;i<=n;i++) cin>>s[i]; sort(s+1,s+n+1); for (int i=1;i<=n;i++) len[i]=s[i].size(); for (int i=1;i<=n;i++) for (int j=n;j>=1;j--) if (i!=j && s[i][len[i]-1]==s[j][0]) add_edge(i,j); for (int i=1;i<=n;i++) cnt[s[i][0]-'a']++,cnt[s[i][len[i]-1]-'a']--; int k=0,h; for (int i=0;i<26;i++){ if (cnt[i]==1) k++,h=i; if (cnt[i]==2) k=2; if (k==2) break; } if (k==2) cout<<"***\n"; else if (k==1){ for (int i=1;i<=n;i++) if (s[i][0]-'a'==h) dfs(i); } else { for (int i=1;i<=n;i++) dfs(i); } if (!flag) { cout<<"***\n"; return 0; } cout<<s[sta[0]]; for (int i=1;i<top;i++) cout<<'.'<<s[sta[i]]; cout<<endl; return 0; }
转载请注明原文地址: https://www.6miu.com/read-5032178.html

最新回复(0)