词链
题目链接:https://www.luogu.com.cn/problem/P1127
题意:
给定n个单词,后面单词的第一个字母与前面单词的最后一个字母相同,输出字典序最小的排列
思路:
经典欧拉路径问题
单词作为边,该单词的第一个字母和最后一个字母作为节点建图
1.建立并查集,判断图的连通性
2.观察节点的入度和出度,判断是否满足欧拉路径条件
- Hierholzer 算法递归遍历边,将答案压栈
int n;
struct edge{
int v;string word;
};
vector<edge>e[26];
int ieg[maxn];
int oeg[maxn];
int f[maxn];
int find(int x){
if(f[x]!=x)f[x]=find(f[x]);return f[x];
}
void merge(int x,int y){
if(find(x)!=find(y)){
f[find(x)]=find(y);
}
}
bool cmp(edge a,edge b){
return a.word<b.word;
}
stack<string>stk;
int now[maxn];
void dfs(int u){
for(int i=now[u];i<e[u].size();i=now[u]){
now[u]=i+1;
dfs(e[u][i].v);
stk.push(e[u][i].word);
}
}
void solve(){
cin>>n;
rep(i,0,26)f[i]=i;
vector<int>k;
int st=25,ed=0;
rep(i,1,n){
string s;cin>>s;
int a=s[0]-'a';
int b=s[s.size()-1]-'a';
st=min(st,a);
ed=max(ed,b);
merge(a,b);
k.pb(a);k.pb(b);
e[a].pb((edge){b,s});
oeg[a]++;
ieg[b]++;
}
int fa=find(k[0]);
for(int i=0;i<k.size();i++){
if(fa!=find(k[i])){
cout<<"***"<<endl;return;
}
}
int cnt=0;
for(int i=0;i<26;i++){
if(oeg[i]!=ieg[i]){
cnt++;
if(abs(oeg[i]-ieg[i])>1){
cout<<"***"<<endl;return;
}
if(oeg[i]-ieg[i]==1){
st=i;
}
else if(ieg[i]-oeg[i]==1){
ed=i;
}
}
}
if(cnt>2){
cout<<"***"<<endl;return;
}
for(int i=0;i<26;i++){
sort(e[i].begin(),e[i].end(),cmp);
}
dfs(st);
while(stk.size()){
cout<<stk.top();
stk.pop();
if(stk.size())cout<<'.';
}
}

浙公网安备 33010602011771号